Skip to content

Commit 62eb47b

Browse files
authored
Merge pull request hoisie#199 from hoisie/malformed-scgi
Gracefully handle malformed SCGI requests
2 parents 5e5e951 + 2f9512f commit 62eb47b

File tree

2 files changed

+32
-6
lines changed

2 files changed

+32
-6
lines changed

scgi.go

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -97,18 +97,20 @@ func (s *Server) readScgiRequest(fd io.ReadWriteCloser) (*http.Request, error) {
9797
reader := bufio.NewReader(fd)
9898
line, err := reader.ReadString(':')
9999
if err != nil {
100-
s.Logger.Println("Error during SCGI read: ", err.Error())
100+
return nil, err
101+
}
102+
length, err := strconv.Atoi(line[0 : len(line)-1])
103+
if err != nil {
104+
return nil, err
101105
}
102-
length, _ := strconv.Atoi(line[0 : len(line)-1])
103106
if length > 16384 {
104-
s.Logger.Println("Error: max header size is 16k")
107+
return nil, errors.New("Max header size is 16k")
105108
}
106109
headerData := make([]byte, length)
107110
_, err = reader.Read(headerData)
108111
if err != nil {
109112
return nil, err
110113
}
111-
112114
b, err := reader.ReadByte()
113115
if err != nil {
114116
return nil, err
@@ -138,14 +140,15 @@ func (s *Server) readScgiRequest(fd io.ReadWriteCloser) (*http.Request, error) {
138140
}
139141

140142
func (s *Server) handleScgiRequest(fd io.ReadWriteCloser) {
143+
defer fd.Close()
141144
req, err := s.readScgiRequest(fd)
142145
if err != nil {
143-
s.Logger.Println("SCGI error: %q", err.Error())
146+
s.Logger.Println("Error reading SCGI request: %q", err.Error())
147+
return
144148
}
145149
sc := scgiConn{fd, req, make(map[string][]string), false}
146150
s.routeHandler(req, &sc)
147151
sc.finishRequest()
148-
fd.Close()
149152
}
150153

151154
func (s *Server) listenAndServeScgi(addr string) error {

web_test.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,29 @@ func TestNoColorOutput(t *testing.T) {
591591
}
592592
}
593593

594+
// a malformed SCGI request should be discarded and not cause a panic
595+
func TestMaformedScgiRequest(t *testing.T) {
596+
var headerBuf bytes.Buffer
597+
598+
headerBuf.WriteString("CONTENT_LENGTH")
599+
headerBuf.WriteByte(0)
600+
headerBuf.WriteString("0")
601+
headerBuf.WriteByte(0)
602+
headerData := headerBuf.Bytes()
603+
604+
var buf bytes.Buffer
605+
fmt.Fprintf(&buf, "%d:", len(headerData))
606+
buf.Write(headerData)
607+
buf.WriteByte(',')
608+
609+
var output bytes.Buffer
610+
nb := ioBuffer{input: &buf, output: &output}
611+
mainServer.handleScgiRequest(&nb)
612+
if !nb.closed {
613+
t.Fatalf("The connection should have been closed")
614+
}
615+
}
616+
594617
type TestHandler struct{}
595618

596619
func (t *TestHandler) ServeHTTP(c http.ResponseWriter, req *http.Request) {

0 commit comments

Comments
 (0)