encoding/json: make error capture logic in recover more type safe

Rather than only ignoring runtime.Error panics, which are a very
narrow set of possible panic values, switch it such that the json
package only captures panic values that have been properly wrapped
in a jsonError struct. This ensures that only intentional panics
originating from the json package are captured.

Fixes #23012

Change-Id: I5e85200259edd2abb1b0512ce6cc288849151a6d
Reviewed-on: https://go-review.googlesource.com/94019
Run-TryBot: Joe Tsai <thebrokentoaster@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
Joe Tsai 2017-12-05 22:53:48 -08:00 committed by Joe Tsai
parent 70a04f6880
commit 91a6a2a30f
4 changed files with 43 additions and 12 deletions

View file

@ -17,7 +17,6 @@ import (
"fmt"
"math"
"reflect"
"runtime"
"sort"
"strconv"
"strings"
@ -286,21 +285,20 @@ func newEncodeState() *encodeState {
func (e *encodeState) marshal(v interface{}, opts encOpts) (err error) {
defer func() {
if r := recover(); r != nil {
if _, ok := r.(runtime.Error); ok {
if je, ok := r.(jsonError); ok {
err = je.error
} else {
panic(r)
}
if s, ok := r.(string); ok {
panic(s)
}
err = r.(error)
}
}()
e.reflectValue(reflect.ValueOf(v), opts)
return nil
}
// error aborts the encoding by panicking with err wrapped in jsonError.
func (e *encodeState) error(err error) {
panic(err)
panic(jsonError{err})
}
func isEmptyValue(v reflect.Value) bool {