Skip to content

Commit

Permalink
Update UnmarshalJSON in codes package
Browse files Browse the repository at this point in the history
Try fix Issue 61477 reported by libFuzzer in OSS-Fuzz
  • Loading branch information
Danielius1922 committed Nov 8, 2023
1 parent b34d9da commit 1816fa5
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 5 deletions.
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)
})
}

0 comments on commit 1816fa5

Please sign in to comment.