Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update UnmarshalJSON in codes package #509

Merged
merged 1 commit into from
Nov 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/workflows/cifuzz.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
name: CIFuzz
on: [pull_request]
on:
pull_request:
workflow_dispatch:
permissions: {}
jobs:
Fuzzing:
Expand Down
23 changes: 22 additions & 1 deletion message/codes/codes.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ const (

const _maxCode = 255

var _maxCodeLen int

var strToCode = map[string]Code{
`"GET"`: GET,
`"POST"`: POST,
Expand Down Expand Up @@ -90,6 +92,21 @@ var strToCode = map[string]Code{
`"Abort"`: Abort,
}

func getMaxCodeLen() int {
// max uint32 as string binary representation: "0b" + 32 digits
max := 34
for k := range strToCode {
if len(k) > max {
max = len(k)
}
}
return max
}

func init() {
_maxCodeLen = getMaxCodeLen()
}

// UnmarshalJSON unmarshals b into the Code.
func (c *Code) UnmarshalJSON(b []byte) error {
// From json.Unmarshaler: By convention, to approximate the behavior of
Expand All @@ -102,6 +119,10 @@ func (c *Code) UnmarshalJSON(b []byte) error {
return fmt.Errorf("nil receiver passed to UnmarshalJSON")
}

if len(b) > _maxCodeLen {
return fmt.Errorf("invalid code: input too large(length=%d)", len(b))
}

if ci, err := strconv.ParseUint(string(b), 10, 32); err == nil {
if ci >= _maxCode {
return fmt.Errorf("invalid code: %q", ci)
Expand All @@ -115,5 +136,5 @@ func (c *Code) UnmarshalJSON(b []byte) error {
*c = jc
return nil
}
return fmt.Errorf("invalid code: %q", string(b))
return fmt.Errorf("invalid code: %v", b)
}
37 changes: 34 additions & 3 deletions message/codes/codes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package codes

import (
"encoding/json"
"strconv"
"testing"

"github.com/stretchr/testify/require"
Expand All @@ -14,6 +15,24 @@ func TestJSONUnmarshal(t *testing.T) {
err := json.Unmarshal([]byte(in), &got)
require.NoError(t, err)
require.Equal(t, want, got)

inNumeric := "["
for i, c := range want {
if i > 0 {
inNumeric += ","
}
inNumeric += strconv.FormatUint(uint64(c), 10)
}
inNumeric += "]"
err = json.Unmarshal([]byte(inNumeric), &got)
require.NoError(t, err)
require.Equal(t, want, got)
}

func TestUnmarshalJSONNoop(t *testing.T) {
var got Code
err := got.UnmarshalJSON([]byte("null"))
require.NoError(t, err)
}

func TestUnmarshalJSONNilReceiver(t *testing.T) {
Expand All @@ -24,11 +43,18 @@ func TestUnmarshalJSONNilReceiver(t *testing.T) {
}

func TestUnmarshalJSONUnknownInput(t *testing.T) {
var got Code
for _, in := range [][]byte{[]byte(""), []byte("xxx"), []byte("Code(17)"), nil} {
inputs := [][]byte{nil, []byte(""), []byte("xxx"), []byte("Code(17)"), []byte("255")}
for _, in := range inputs {
var got Code
err := got.UnmarshalJSON(in)
require.Error(t, err)
}

var got Code
longStr := "This is a very long string that is longer than the max code length"
require.True(t, len(longStr) > getMaxCodeLen())
err := got.UnmarshalJSON([]byte(longStr))
require.Error(t, err)
}

func TestUnmarshalJSONMarshalUnmarshal(t *testing.T) {
Expand Down Expand Up @@ -59,11 +85,16 @@ func TestCodeToString(t *testing.T) {
}

func FuzzUnmarshalJSON(f *testing.F) {
f.Add([]byte("null"))
f.Add([]byte("xxx"))
f.Add([]byte("Code(17)"))
f.Add([]byte("0b101010"))
f.Add([]byte("0o52"))
f.Add([]byte("0x2a"))
f.Add([]byte("42"))

f.Fuzz(func(t *testing.T, input_data []byte) {
var got *Code
var got Code
_ = got.UnmarshalJSON(input_data)
})
}
Loading