From 108c644938fadc62a8a0c304f8c85c0b08926ee3 Mon Sep 17 00:00:00 2001 From: Linh Vo Date: Wed, 24 May 2017 13:57:47 -0500 Subject: [PATCH 1/3] #312 validate unkown query params --- handler.go | 21 +++++++++++++++++++++ handler_test.go | 10 ++++++++++ 2 files changed, 31 insertions(+) diff --git a/handler.go b/handler.go index c4a98d04c..a2e8868f1 100644 --- a/handler.go +++ b/handler.go @@ -42,6 +42,7 @@ import ( _ "github.com/pilosa/pilosa/statik" "github.com/rakyll/statik/fs" + "unicode" ) // Handler represents an HTTP handler. @@ -843,6 +844,12 @@ func (h *Handler) readProtobufQueryRequest(r *http.Request) (*QueryRequest, erro // readURLQueryRequest parses query parameters from URL parameters from r. func (h *Handler) readURLQueryRequest(r *http.Request) (*QueryRequest, error) { q := r.URL.Query() + validQuery := h.getValidURLQuery(r) + for key, _ := range q { + if _, ok := validQuery[key]; !ok { + return nil, errors.New("invalid query params") + } + } // Parse query string. buf, err := ioutil.ReadAll(r.Body) @@ -875,6 +882,20 @@ func (h *Handler) readURLQueryRequest(r *http.Request) (*QueryRequest, error) { }, nil } +func (h *Handler) getValidURLQuery(r *http.Request) map[string]bool { + validQuery := make(map[string]bool) + args := reflect.ValueOf(QueryRequest{}) + + for i := 0; i < args.Type().NumField(); i++ { + fieldName := args.Type().Field(i).Name + chars := []rune(fieldName) + chars[0] = unicode.ToLower(chars[0]) + fieldName = string(chars) + validQuery[fieldName] = true + } + return validQuery +} + // writeQueryResponse writes the response from the executor to w. func (h *Handler) writeQueryResponse(w http.ResponseWriter, r *http.Request, resp *QueryResponse) error { if strings.Contains(r.Header.Get("Accept"), "application/x-protobuf") { diff --git a/handler_test.go b/handler_test.go index 6744e74ea..427ad043e 100644 --- a/handler_test.go +++ b/handler_test.go @@ -209,6 +209,16 @@ func TestHandler_Query_Args_Err(t *testing.T) { t.Fatalf("unexpected body: %q", body) } } +func TestHandler_Query_Params_Err(t *testing.T) { + w := httptest.NewRecorder() + NewHandler().ServeHTTP(w, MustNewHTTPRequest("POST", "/index/idx0/query?slices=0,1&db=sample", strings.NewReader("Bitmap(id=100)"))) + if w.Code != http.StatusBadRequest { + t.Fatalf("unexpected status code: %d", w.Code) + } else if body := w.Body.String(); body != `{"error":"invalid query params"}`+"\n" { + t.Fatalf("unexpected body: %q", body) + } + +} // Ensure the handler can execute a query with a uint64 response as JSON. func TestHandler_Query_Uint64_JSON(t *testing.T) { From e34e9f9789a3fbb2266413298c03362f04a0d046 Mon Sep 17 00:00:00 2001 From: Linh Vo Date: Thu, 25 May 2017 11:48:08 -0500 Subject: [PATCH 2/3] fixed comment, update validQueryArgs --- ctl/export.go | 2 +- handler.go | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/ctl/export.go b/ctl/export.go index fa6277f16..295e10039 100644 --- a/ctl/export.go +++ b/ctl/export.go @@ -31,7 +31,7 @@ type ExportCommand struct { // Name of the index & frame to export from. Index string Frame string - View string + View string // Filename to export to. Path string diff --git a/handler.go b/handler.go index a2e8868f1..f7b956bc6 100644 --- a/handler.go +++ b/handler.go @@ -844,7 +844,7 @@ func (h *Handler) readProtobufQueryRequest(r *http.Request) (*QueryRequest, erro // readURLQueryRequest parses query parameters from URL parameters from r. func (h *Handler) readURLQueryRequest(r *http.Request) (*QueryRequest, error) { q := r.URL.Query() - validQuery := h.getValidURLQuery(r) + validQuery := validOptions(QueryRequest{}) for key, _ := range q { if _, ok := validQuery[key]; !ok { return nil, errors.New("invalid query params") @@ -882,12 +882,13 @@ func (h *Handler) readURLQueryRequest(r *http.Request) (*QueryRequest, error) { }, nil } -func (h *Handler) getValidURLQuery(r *http.Request) map[string]bool { +// validOptions return all attributes of an interface with lower first character. +func validOptions(v interface{}) map[string]bool { validQuery := make(map[string]bool) - args := reflect.ValueOf(QueryRequest{}) + argsType := reflect.ValueOf(v) - for i := 0; i < args.Type().NumField(); i++ { - fieldName := args.Type().Field(i).Name + for i := 0; i < argsType.Type().NumField(); i++ { + fieldName := argsType.Type().Field(i).Name chars := []rune(fieldName) chars[0] = unicode.ToLower(chars[0]) fieldName = string(chars) From 3706fc90222d64877a2c79f994a44b5583fff615 Mon Sep 17 00:00:00 2001 From: Linh Vo Date: Thu, 25 May 2017 13:04:38 -0500 Subject: [PATCH 3/3] changed argType --- handler.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/handler.go b/handler.go index f7b956bc6..c4a2c2a06 100644 --- a/handler.go +++ b/handler.go @@ -885,10 +885,10 @@ func (h *Handler) readURLQueryRequest(r *http.Request) (*QueryRequest, error) { // validOptions return all attributes of an interface with lower first character. func validOptions(v interface{}) map[string]bool { validQuery := make(map[string]bool) - argsType := reflect.ValueOf(v) + argsType := reflect.ValueOf(v).Type() - for i := 0; i < argsType.Type().NumField(); i++ { - fieldName := argsType.Type().Field(i).Name + for i := 0; i < argsType.NumField(); i++ { + fieldName := argsType.Field(i).Name chars := []rune(fieldName) chars[0] = unicode.ToLower(chars[0]) fieldName = string(chars)