From 4d0003a2bbba11937cbc08a2af9c9956bb1917b7 Mon Sep 17 00:00:00 2001 From: Massimiliano Pippi Date: Fri, 11 Oct 2019 15:15:37 +0200 Subject: [PATCH 1/2] avoid calling cloud API if vid or pid are invalid --- commands/board/list.go | 18 ++++++++++++++---- commands/board/list_test.go | 16 ++++++++++------ 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/commands/board/list.go b/commands/board/list.go index 29865093ed1..443e3dd6158 100644 --- a/commands/board/list.go +++ b/commands/board/list.go @@ -22,6 +22,7 @@ import ( "fmt" "io/ioutil" "net/http" + "strconv" "sync" "github.com/arduino/arduino-cli/cli/globals" @@ -35,9 +36,18 @@ var ( // ErrNotFound is returned when the API returns 404 ErrNotFound = errors.New("board not found") m sync.Mutex + vidPidURL = "https://builder.arduino.cc/v3/boards/byVidPid" ) -func apiByVidPid(url string) ([]*rpc.BoardListItem, error) { +func apiByVidPid(vid, pid string) ([]*rpc.BoardListItem, error) { + // ensure vid and pid are valid before hitting the API + _, vidErr := strconv.ParseInt(vid, 0, 64) + _, pidErr := strconv.ParseInt(pid, 0, 64) + if vidErr != nil || pidErr != nil { + return nil, errors.Errorf("Invalid vid/pid value: '%s:%s'", vid, pid) + } + + url := fmt.Sprintf("%s/%s/%s", vidPidURL, vid, pid) retVal := []*rpc.BoardListItem{} req, _ := http.NewRequest("GET", url, nil) req.Header = globals.NewHTTPClientHeader() @@ -110,10 +120,10 @@ func List(instanceID int32) ([]*rpc.DetectedPort, error) { // the builder API if len(b) == 0 { logrus.Debug("Querying builder API for board identification...") - url := fmt.Sprintf("https://builder.arduino.cc/v3/boards/byVidPid/%s/%s", + items, err := apiByVidPid( port.IdentificationPrefs.Get("vid"), - port.IdentificationPrefs.Get("pid")) - items, err := apiByVidPid(url) + port.IdentificationPrefs.Get("pid"), + ) if err == ErrNotFound { // the board couldn't be detected, print a warning logrus.Debug("Board not recognized") diff --git a/commands/board/list_test.go b/commands/board/list_test.go index 65fcaaa8cfb..5309d166f80 100644 --- a/commands/board/list_test.go +++ b/commands/board/list_test.go @@ -40,14 +40,15 @@ func TestGetByVidPid(t *testing.T) { })) defer ts.Close() - res, err := apiByVidPid(ts.URL) + vidPidURL = ts.URL + res, err := apiByVidPid("0x0420", "0x0069") require.Nil(t, err) require.Len(t, res, 1) require.Equal(t, "Arduino/Genuino MKR1000", res[0].Name) require.Equal(t, "arduino:samd:mkr1000", res[0].FQBN) - // wrong url - res, err = apiByVidPid("http://0.0.0.0") + // wrong vid/pid + res, err = apiByVidPid("foo", "") require.NotNil(t, err) } @@ -57,7 +58,8 @@ func TestGetByVidPidNotFound(t *testing.T) { })) defer ts.Close() - res, err := apiByVidPid(ts.URL) + vidPidURL = ts.URL + res, err := apiByVidPid("0x0420", "0x0069") require.NotNil(t, err) require.Equal(t, "board not found", err.Error()) require.Len(t, res, 0) @@ -70,7 +72,8 @@ func TestGetByVidPid5xx(t *testing.T) { })) defer ts.Close() - res, err := apiByVidPid(ts.URL) + vidPidURL = ts.URL + res, err := apiByVidPid("0x0420", "0x0069") require.NotNil(t, err) require.Equal(t, "the server responded with status 500 Internal Server Error", err.Error()) require.Len(t, res, 0) @@ -82,7 +85,8 @@ func TestGetByVidPidMalformedResponse(t *testing.T) { })) defer ts.Close() - res, err := apiByVidPid(ts.URL) + vidPidURL = ts.URL + res, err := apiByVidPid("0x0420", "0x0069") require.NotNil(t, err) require.Equal(t, "wrong format in server response", err.Error()) require.Len(t, res, 0) From 7db5932758ea73b12bc1d89d203c85c3ed115415 Mon Sep 17 00:00:00 2001 From: Massimiliano Pippi Date: Tue, 15 Oct 2019 12:27:55 +0200 Subject: [PATCH 2/2] user regex --- commands/board/list.go | 12 +++++++----- commands/board/list_test.go | 6 +++--- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/commands/board/list.go b/commands/board/list.go index 443e3dd6158..577aa478b6c 100644 --- a/commands/board/list.go +++ b/commands/board/list.go @@ -22,7 +22,7 @@ import ( "fmt" "io/ioutil" "net/http" - "strconv" + "regexp" "sync" "github.com/arduino/arduino-cli/cli/globals" @@ -37,14 +37,16 @@ var ( ErrNotFound = errors.New("board not found") m sync.Mutex vidPidURL = "https://builder.arduino.cc/v3/boards/byVidPid" + validVidPid = regexp.MustCompile(`0[xX][a-fA-F\d]{4}`) ) func apiByVidPid(vid, pid string) ([]*rpc.BoardListItem, error) { // ensure vid and pid are valid before hitting the API - _, vidErr := strconv.ParseInt(vid, 0, 64) - _, pidErr := strconv.ParseInt(pid, 0, 64) - if vidErr != nil || pidErr != nil { - return nil, errors.Errorf("Invalid vid/pid value: '%s:%s'", vid, pid) + if !validVidPid.MatchString(vid) { + return nil, errors.Errorf("Invalid vid value: '%s'", vid) + } + if !validVidPid.MatchString(pid) { + return nil, errors.Errorf("Invalid pid value: '%s'", pid) } url := fmt.Sprintf("%s/%s/%s", vidPidURL, vid, pid) diff --git a/commands/board/list_test.go b/commands/board/list_test.go index 5309d166f80..4014e791f4a 100644 --- a/commands/board/list_test.go +++ b/commands/board/list_test.go @@ -41,14 +41,14 @@ func TestGetByVidPid(t *testing.T) { defer ts.Close() vidPidURL = ts.URL - res, err := apiByVidPid("0x0420", "0x0069") + res, err := apiByVidPid("0xf420", "0XF069") require.Nil(t, err) require.Len(t, res, 1) require.Equal(t, "Arduino/Genuino MKR1000", res[0].Name) require.Equal(t, "arduino:samd:mkr1000", res[0].FQBN) - // wrong vid/pid - res, err = apiByVidPid("foo", "") + // wrong vid (too long), wrong pid (not an hex value) + res, err = apiByVidPid("0xfffff", "0xDEFG") require.NotNil(t, err) }