Skip to content

Commit 2f9512f

Browse files
committed
Gracefully handle malformed SCGI requests
Previously, malformed SCGI requests would cause a panic when they were processed. Gracefully handle malformed SCGI requests. Also, add some additional error checking when parsing the length of the request, and clean up the code related to logging SCGI errors. Fixes hoisie#166
1 parent 5e5e951 commit 2f9512f

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)