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
 	}