playground: Stop reading HTTP request as soon as limit is reached.
Request handlers were reading the entire request before checking
length, making compilerd vulnerable to DoS.
Change-Id: I75d05d6f71a1886b8e84549fc1f3d4e9da83c73f
diff --git a/go/src/playground/compilerd/compile.go b/go/src/playground/compilerd/compile.go
index 602133f..8666a3a 100644
--- a/go/src/playground/compilerd/compile.go
+++ b/go/src/playground/compilerd/compile.go
@@ -51,7 +51,9 @@
}
// Check method and read POST body.
- requestBody := getPostBody(w, r)
+ // Limit is set to maxSize+1 to allow distinguishing between exactly maxSize
+ // and larger than maxSize requests.
+ requestBody := getPostBody(w, r, maxSize+1)
if requestBody == nil {
return
}
diff --git a/go/src/playground/compilerd/main.go b/go/src/playground/compilerd/main.go
index 07d1610..cf30a43 100644
--- a/go/src/playground/compilerd/main.go
+++ b/go/src/playground/compilerd/main.go
@@ -10,6 +10,7 @@
"encoding/hex"
"flag"
"fmt"
+ "io"
"log"
"math/rand"
"net/http"
@@ -160,16 +161,17 @@
return true
}
-// Checks if the POST method was used and returns the request body.
+// Checks if the POST method was used and returns the first limit bytes of the
+// request body.
// Returns nil iff response processing should not continue.
-func getPostBody(w http.ResponseWriter, r *http.Request) []byte {
+func getPostBody(w http.ResponseWriter, r *http.Request, limit int) []byte {
if r.Body == nil || r.Method != "POST" {
w.WriteHeader(http.StatusBadRequest)
return nil
}
buf := new(bytes.Buffer)
- buf.ReadFrom(r.Body)
+ buf.ReadFrom(io.LimitReader(r.Body, int64(limit)))
return buf.Bytes()
}
diff --git a/go/src/playground/compilerd/storage.go b/go/src/playground/compilerd/storage.go
index 1cf437e..fe4a75b 100644
--- a/go/src/playground/compilerd/storage.go
+++ b/go/src/playground/compilerd/storage.go
@@ -197,7 +197,9 @@
}
// Check method and read POST body.
- requestBody := getPostBody(w, r)
+ // Limit is set to maxSize+1 to allow distinguishing between exactly maxSize
+ // and larger than maxSize requests.
+ requestBody := getPostBody(w, r, maxSize+1)
if requestBody == nil {
return
}