@@ -16,6 +16,10 @@ import (
16
16
"sync"
17
17
)
18
18
19
+ // TODO: This should be a distinguishable error (ErrMessageTooLarge)
20
+ // to allow mime/multipart to detect it.
21
+ var errMessageTooLarge = errors .New ("message too large" )
22
+
19
23
// A Reader implements convenience methods for reading requests
20
24
// or responses from a text protocol network connection.
21
25
type Reader struct {
@@ -36,27 +40,33 @@ func NewReader(r *bufio.Reader) *Reader {
36
40
// ReadLine reads a single line from r,
37
41
// eliding the final \n or \r\n from the returned string.
38
42
func (r * Reader ) ReadLine () (string , error ) {
39
- line , err := r .readLineSlice ()
43
+ line , err := r .readLineSlice (- 1 )
40
44
return string (line ), err
41
45
}
42
46
43
47
// ReadLineBytes is like [Reader.ReadLine] but returns a []byte instead of a string.
44
48
func (r * Reader ) ReadLineBytes () ([]byte , error ) {
45
- line , err := r .readLineSlice ()
49
+ line , err := r .readLineSlice (- 1 )
46
50
if line != nil {
47
51
line = bytes .Clone (line )
48
52
}
49
53
return line , err
50
54
}
51
55
52
- func (r * Reader ) readLineSlice () ([]byte , error ) {
56
+ // readLineSlice reads a single line from r,
57
+ // up to lim bytes long (or unlimited if lim is less than 0),
58
+ // eliding the final \r or \r\n from the returned string.
59
+ func (r * Reader ) readLineSlice (lim int64 ) ([]byte , error ) {
53
60
r .closeDot ()
54
61
var line []byte
55
62
for {
56
63
l , more , err := r .R .ReadLine ()
57
64
if err != nil {
58
65
return nil , err
59
66
}
67
+ if lim >= 0 && int64 (len (line ))+ int64 (len (l )) > lim {
68
+ return nil , errMessageTooLarge
69
+ }
60
70
// Avoid the copy if the first call produced a full line.
61
71
if line == nil && ! more {
62
72
return l , nil
@@ -88,7 +98,7 @@ func (r *Reader) readLineSlice() ([]byte, error) {
88
98
//
89
99
// Empty lines are never continued.
90
100
func (r * Reader ) ReadContinuedLine () (string , error ) {
91
- line , err := r .readContinuedLineSlice (noValidation )
101
+ line , err := r .readContinuedLineSlice (- 1 , noValidation )
92
102
return string (line ), err
93
103
}
94
104
@@ -109,7 +119,7 @@ func trim(s []byte) []byte {
109
119
// ReadContinuedLineBytes is like [Reader.ReadContinuedLine] but
110
120
// returns a []byte instead of a string.
111
121
func (r * Reader ) ReadContinuedLineBytes () ([]byte , error ) {
112
- line , err := r .readContinuedLineSlice (noValidation )
122
+ line , err := r .readContinuedLineSlice (- 1 , noValidation )
113
123
if line != nil {
114
124
line = bytes .Clone (line )
115
125
}
@@ -120,13 +130,14 @@ func (r *Reader) ReadContinuedLineBytes() ([]byte, error) {
120
130
// returning a byte slice with all lines. The validateFirstLine function
121
131
// is run on the first read line, and if it returns an error then this
122
132
// error is returned from readContinuedLineSlice.
123
- func (r * Reader ) readContinuedLineSlice (validateFirstLine func ([]byte ) error ) ([]byte , error ) {
133
+ // It reads up to lim bytes of data (or unlimited if lim is less than 0).
134
+ func (r * Reader ) readContinuedLineSlice (lim int64 , validateFirstLine func ([]byte ) error ) ([]byte , error ) {
124
135
if validateFirstLine == nil {
125
136
return nil , fmt .Errorf ("missing validateFirstLine func" )
126
137
}
127
138
128
139
// Read the first line.
129
- line , err := r .readLineSlice ()
140
+ line , err := r .readLineSlice (lim )
130
141
if err != nil {
131
142
return nil , err
132
143
}
@@ -154,13 +165,21 @@ func (r *Reader) readContinuedLineSlice(validateFirstLine func([]byte) error) ([
154
165
// copy the slice into buf.
155
166
r .buf = append (r .buf [:0 ], trim (line )... )
156
167
168
+ if lim < 0 {
169
+ lim = math .MaxInt64
170
+ }
171
+ lim -= int64 (len (r .buf ))
172
+
157
173
// Read continuation lines.
158
174
for r .skipSpace () > 0 {
159
- line , err := r .readLineSlice ()
175
+ r .buf = append (r .buf , ' ' )
176
+ if int64 (len (r .buf )) >= lim {
177
+ return nil , errMessageTooLarge
178
+ }
179
+ line , err := r .readLineSlice (lim - int64 (len (r .buf )))
160
180
if err != nil {
161
181
break
162
182
}
163
- r .buf = append (r .buf , ' ' )
164
183
r .buf = append (r .buf , trim (line )... )
165
184
}
166
185
return r .buf , nil
@@ -507,15 +526,16 @@ func readMIMEHeader(r *Reader, maxMemory, maxHeaders int64) (MIMEHeader, error)
507
526
508
527
// The first line cannot start with a leading space.
509
528
if buf , err := r .R .Peek (1 ); err == nil && (buf [0 ] == ' ' || buf [0 ] == '\t' ) {
510
- line , err := r .readLineSlice ()
529
+ const errorLimit = 80 // arbitrary limit on how much of the line we'll quote
530
+ line , err := r .readLineSlice (errorLimit )
511
531
if err != nil {
512
532
return m , err
513
533
}
514
534
return m , ProtocolError ("malformed MIME header initial line: " + string (line ))
515
535
}
516
536
517
537
for {
518
- kv , err := r .readContinuedLineSlice (mustHaveFieldNameColon )
538
+ kv , err := r .readContinuedLineSlice (maxMemory , mustHaveFieldNameColon )
519
539
if len (kv ) == 0 {
520
540
return m , err
521
541
}
@@ -537,7 +557,7 @@ func readMIMEHeader(r *Reader, maxMemory, maxHeaders int64) (MIMEHeader, error)
537
557
538
558
maxHeaders --
539
559
if maxHeaders < 0 {
540
- return nil , errors . New ( "message too large" )
560
+ return nil , errMessageTooLarge
541
561
}
542
562
543
563
// Skip initial spaces in value.
@@ -550,9 +570,7 @@ func readMIMEHeader(r *Reader, maxMemory, maxHeaders int64) (MIMEHeader, error)
550
570
}
551
571
maxMemory -= int64 (len (value ))
552
572
if maxMemory < 0 {
553
- // TODO: This should be a distinguishable error (ErrMessageTooLarge)
554
- // to allow mime/multipart to detect it.
555
- return m , errors .New ("message too large" )
573
+ return m , errMessageTooLarge
556
574
}
557
575
if vv == nil && len (strs ) > 0 {
558
576
// More than likely this will be a single-element key.
0 commit comments