mirror of
https://github.com/v2fly/v2ray-core.git
synced 2025-07-05 16:38:17 -04:00
Fix: json.Reader: fill output bytes as much as possible
Fix JSON parsing state machine so Read([]byte) can accept byte array of any length. This fixes a infinite read with io.ReadFull().
This commit is contained in:
parent
ddc6312c5d
commit
f0236233f3
@ -28,17 +28,28 @@ type Reader struct {
|
|||||||
io.Reader
|
io.Reader
|
||||||
|
|
||||||
state State
|
state State
|
||||||
|
pending []byte
|
||||||
br *buf.BufferedReader
|
br *buf.BufferedReader
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read implements io.Reader.Read(). Buffer must be at least 3 bytes.
|
// Read implements io.Reader.Read().
|
||||||
func (v *Reader) Read(b []byte) (int, error) {
|
func (v *Reader) Read(b []byte) (int, error) {
|
||||||
if v.br == nil {
|
if v.br == nil {
|
||||||
v.br = &buf.BufferedReader{Reader: buf.NewReader(v.Reader)}
|
v.br = &buf.BufferedReader{Reader: buf.NewReader(v.Reader)}
|
||||||
}
|
}
|
||||||
|
|
||||||
p := b[:0]
|
p := b[:0]
|
||||||
for len(p) < len(b)-2 {
|
for len(p) < len(b) {
|
||||||
|
if len(v.pending) > 0 {
|
||||||
|
max := len(b) - len(p)
|
||||||
|
if max > len(v.pending) {
|
||||||
|
max = len(v.pending)
|
||||||
|
}
|
||||||
|
p = append(p, v.pending[:max]...)
|
||||||
|
v.pending = v.pending[max:]
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
x, err := v.br.ReadByte()
|
x, err := v.br.ReadByte()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if len(p) == 0 {
|
if len(p) == 0 {
|
||||||
@ -57,6 +68,7 @@ func (v *Reader) Read(b []byte) (int, error) {
|
|||||||
p = append(p, x)
|
p = append(p, x)
|
||||||
case '\\':
|
case '\\':
|
||||||
v.state = StateEscape
|
v.state = StateEscape
|
||||||
|
p = append(p, x)
|
||||||
case '#':
|
case '#':
|
||||||
v.state = StateComment
|
v.state = StateComment
|
||||||
case '/':
|
case '/':
|
||||||
@ -65,7 +77,7 @@ func (v *Reader) Read(b []byte) (int, error) {
|
|||||||
p = append(p, x)
|
p = append(p, x)
|
||||||
}
|
}
|
||||||
case StateEscape:
|
case StateEscape:
|
||||||
p = append(p, '\\', x)
|
p = append(p, x)
|
||||||
v.state = StateContent
|
v.state = StateContent
|
||||||
case StateDoubleQuote:
|
case StateDoubleQuote:
|
||||||
switch x {
|
switch x {
|
||||||
@ -74,11 +86,12 @@ func (v *Reader) Read(b []byte) (int, error) {
|
|||||||
p = append(p, x)
|
p = append(p, x)
|
||||||
case '\\':
|
case '\\':
|
||||||
v.state = StateDoubleQuoteEscape
|
v.state = StateDoubleQuoteEscape
|
||||||
|
p = append(p, x)
|
||||||
default:
|
default:
|
||||||
p = append(p, x)
|
p = append(p, x)
|
||||||
}
|
}
|
||||||
case StateDoubleQuoteEscape:
|
case StateDoubleQuoteEscape:
|
||||||
p = append(p, '\\', x)
|
p = append(p, x)
|
||||||
v.state = StateDoubleQuote
|
v.state = StateDoubleQuote
|
||||||
case StateSingleQuote:
|
case StateSingleQuote:
|
||||||
switch x {
|
switch x {
|
||||||
@ -87,16 +100,17 @@ func (v *Reader) Read(b []byte) (int, error) {
|
|||||||
p = append(p, x)
|
p = append(p, x)
|
||||||
case '\\':
|
case '\\':
|
||||||
v.state = StateSingleQuoteEscape
|
v.state = StateSingleQuoteEscape
|
||||||
|
p = append(p, x)
|
||||||
default:
|
default:
|
||||||
p = append(p, x)
|
p = append(p, x)
|
||||||
}
|
}
|
||||||
case StateSingleQuoteEscape:
|
case StateSingleQuoteEscape:
|
||||||
p = append(p, '\\', x)
|
p = append(p, x)
|
||||||
v.state = StateSingleQuote
|
v.state = StateSingleQuote
|
||||||
case StateComment:
|
case StateComment:
|
||||||
if x == '\n' {
|
if x == '\n' {
|
||||||
v.state = StateContent
|
v.state = StateContent
|
||||||
p = append(p, '\n')
|
p = append(p, x)
|
||||||
}
|
}
|
||||||
case StateSlash:
|
case StateSlash:
|
||||||
switch x {
|
switch x {
|
||||||
@ -105,14 +119,16 @@ func (v *Reader) Read(b []byte) (int, error) {
|
|||||||
case '*':
|
case '*':
|
||||||
v.state = StateMultilineComment
|
v.state = StateMultilineComment
|
||||||
default:
|
default:
|
||||||
p = append(p, '/', x)
|
v.state = StateContent
|
||||||
|
v.pending = append(v.pending, x)
|
||||||
|
p = append(p, '/')
|
||||||
}
|
}
|
||||||
case StateMultilineComment:
|
case StateMultilineComment:
|
||||||
switch x {
|
switch x {
|
||||||
case '*':
|
case '*':
|
||||||
v.state = StateMultilineCommentStar
|
v.state = StateMultilineCommentStar
|
||||||
case '\n':
|
case '\n':
|
||||||
p = append(p, '\n')
|
p = append(p, x)
|
||||||
}
|
}
|
||||||
case StateMultilineCommentStar:
|
case StateMultilineCommentStar:
|
||||||
switch x {
|
switch x {
|
||||||
@ -121,7 +137,7 @@ func (v *Reader) Read(b []byte) (int, error) {
|
|||||||
case '*':
|
case '*':
|
||||||
// Stay
|
// Stay
|
||||||
case '\n':
|
case '\n':
|
||||||
p = append(p, '\n')
|
p = append(p, x)
|
||||||
default:
|
default:
|
||||||
v.state = StateMultilineComment
|
v.state = StateMultilineComment
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ func TestReader1(t *testing.T) {
|
|||||||
output string
|
output string
|
||||||
}
|
}
|
||||||
|
|
||||||
bufLen := 8
|
bufLen := 1
|
||||||
|
|
||||||
data := []dataStruct{
|
data := []dataStruct{
|
||||||
{"loooooooooooooooooooooooooooooooooooooooog", "loooooooooooooooooooooooooooooooooooooooog"},
|
{"loooooooooooooooooooooooooooooooooooooooog", "loooooooooooooooooooooooooooooooooooooooog"},
|
||||||
@ -70,6 +70,7 @@ func TestReader1(t *testing.T) {
|
|||||||
{`{"t": "\/test"}`, `{"t": "\/test"}`},
|
{`{"t": "\/test"}`, `{"t": "\/test"}`},
|
||||||
{`"\// fake comment"`, `"\// fake comment"`},
|
{`"\// fake comment"`, `"\// fake comment"`},
|
||||||
{`"\/\/\/\/\/"`, `"\/\/\/\/\/"`},
|
{`"\/\/\/\/\/"`, `"\/\/\/\/\/"`},
|
||||||
|
{`/test/test`, `/test/test`},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, testCase := range data {
|
for _, testCase := range data {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user