diff --git a/commands/board/list.go b/commands/board/list.go index 29865093ed1..577aa478b6c 100644 --- a/commands/board/list.go +++ b/commands/board/list.go @@ -22,6 +22,7 @@ import ( "fmt" "io/ioutil" "net/http" + "regexp" "sync" "github.com/arduino/arduino-cli/cli/globals" @@ -35,9 +36,20 @@ 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" + validVidPid = regexp.MustCompile(`0[xX][a-fA-F\d]{4}`) ) -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 + 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) retVal := []*rpc.BoardListItem{} req, _ := http.NewRequest("GET", url, nil) req.Header = globals.NewHTTPClientHeader() @@ -110,10 +122,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..4014e791f4a 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("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 url - res, err = apiByVidPid("http://0.0.0.0") + // wrong vid (too long), wrong pid (not an hex value) + res, err = apiByVidPid("0xfffff", "0xDEFG") 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)