@@ -40,6 +40,7 @@ type chunkedReader struct {
40
40
err error
41
41
buf [2 ]byte
42
42
checkEnd bool // whether need to check for \r\n chunk footer
43
+ excess int64 // "excessive" chunk overhead, for malicious sender detection
43
44
}
44
45
45
46
func (cr * chunkedReader ) beginChunk () {
@@ -49,10 +50,38 @@ func (cr *chunkedReader) beginChunk() {
49
50
if cr .err != nil {
50
51
return
51
52
}
53
+ cr .excess += int64 (len (line )) + 2 // header, plus \r\n after the chunk data
54
+ line = trimTrailingWhitespace (line )
55
+ line , cr .err = removeChunkExtension (line )
56
+ if cr .err != nil {
57
+ return
58
+ }
52
59
cr .n , cr .err = parseHexUint (line )
53
60
if cr .err != nil {
54
61
return
55
62
}
63
+ // A sender who sends one byte per chunk will send 5 bytes of overhead
64
+ // for every byte of data. ("1\r\nX\r\n" to send "X".)
65
+ // We want to allow this, since streaming a byte at a time can be legitimate.
66
+ //
67
+ // A sender can use chunk extensions to add arbitrary amounts of additional
68
+ // data per byte read. ("1;very long extension\r\nX\r\n" to send "X".)
69
+ // We don't want to disallow extensions (although we discard them),
70
+ // but we also don't want to allow a sender to reduce the signal/noise ratio
71
+ // arbitrarily.
72
+ //
73
+ // We track the amount of excess overhead read,
74
+ // and produce an error if it grows too large.
75
+ //
76
+ // Currently, we say that we're willing to accept 16 bytes of overhead per chunk,
77
+ // plus twice the amount of real data in the chunk.
78
+ cr .excess -= 16 + (2 * int64 (cr .n ))
79
+ if cr .excess < 0 {
80
+ cr .excess = 0
81
+ }
82
+ if cr .excess > 16 * 1024 {
83
+ cr .err = errors .New ("chunked encoding contains too much non-data" )
84
+ }
56
85
if cr .n == 0 {
57
86
cr .err = io .EOF
58
87
}
@@ -140,11 +169,6 @@ func readChunkLine(b *bufio.Reader) ([]byte, error) {
140
169
if len (p ) >= maxLineLength {
141
170
return nil , ErrLineTooLong
142
171
}
143
- p = trimTrailingWhitespace (p )
144
- p , err = removeChunkExtension (p )
145
- if err != nil {
146
- return nil , err
147
- }
148
172
return p , nil
149
173
}
150
174
0 commit comments