From 4a3570590ee4dae4cb912c3ab223f8b90ace8b90 Mon Sep 17 00:00:00 2001 From: MatteoPologruto Date: Thu, 18 Jan 2024 17:23:29 +0100 Subject: [PATCH 1/3] Improve the definition of FQBN and explicitly state which characters are allowed --- docs/FAQ.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/FAQ.md b/docs/FAQ.md index a58c40098d5..84599a2bbbf 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -9,7 +9,11 @@ When you run [`arduino-cli board list`][arduino cli board list], your board does ## What's the FQBN string? -For a deeper understanding of how FQBN works, you should understand the [Arduino platform specification][0]. +FQBN stands for Fully Qualified Board Name. It has the following format: +`VENDOR:ARCHITECTURE:BOARD_ID[:MENU_ID=OPTION_ID[,MENU2_ID=OPTION_ID ...]]`, with each `MENU_ID=OPTION_ID` being an +optional key-value pair configuration. Each field accepts letters (`A-Z` or `a-z`), numbers (`0-9`), underscores (`_`), +dashes(`-`) and dots(`.`). The special character `=` is accepted in the configuration value. For a deeper understanding +of how FQBN works, you should understand the [Arduino platform specification][0]. ## How to set multiple board options? From 53b2790f3aa8f8b99d43261497559c506cf8aff2 Mon Sep 17 00:00:00 2001 From: MatteoPologruto Date: Mon, 29 Jan 2024 17:39:29 +0100 Subject: [PATCH 2/3] Enforce fqbn characters validation --- internal/arduino/cores/fqbn.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/internal/arduino/cores/fqbn.go b/internal/arduino/cores/fqbn.go index c5b4384ae5d..8c6ef74ea39 100644 --- a/internal/arduino/cores/fqbn.go +++ b/internal/arduino/cores/fqbn.go @@ -17,6 +17,7 @@ package cores import ( "fmt" + "regexp" "strings" properties "github.com/arduino/go-properties-orderedmap" @@ -57,6 +58,13 @@ func ParseFQBN(fqbnIn string) (*FQBN, error) { if fqbn.BoardID == "" { return nil, fmt.Errorf(tr("empty board identifier")) } + // Check if the fqbn contains invalid characters + fqbnValidationRegex := regexp.MustCompile(`^[a-zA-Z0-9_.-]*$`) + for i := 0; i < 3; i++ { + if !fqbnValidationRegex.MatchString(fqbnParts[i]) { + return nil, fmt.Errorf(tr("fqbn's field %s contains an invalid character"), fqbnParts[i]) + } + } if len(fqbnParts) > 3 { for _, pair := range strings.Split(fqbnParts[3], ",") { parts := strings.SplitN(pair, "=", 2) @@ -68,6 +76,14 @@ func ParseFQBN(fqbnIn string) (*FQBN, error) { if k == "" { return nil, fmt.Errorf(tr("invalid config option: %s"), pair) } + if !fqbnValidationRegex.MatchString(k) { + return nil, fmt.Errorf(tr("config key %s contains an invalid character"), k) + } + // The config value can also contain the = symbol + valueValidationRegex := regexp.MustCompile(`^[a-zA-Z0-9=_.-]*$`) + if !valueValidationRegex.MatchString(v) { + return nil, fmt.Errorf(tr("config value %s contains an invalid character"), v) + } fqbn.Configs.Set(k, v) } } From 0f4bcf22808483fbc320d8a26fe74e5fc7f0c783 Mon Sep 17 00:00:00 2001 From: MatteoPologruto Date: Mon, 29 Jan 2024 17:47:52 +0100 Subject: [PATCH 3/3] Test that an error is returned when the FQBN contains an invalid character --- internal/arduino/cores/fqbn_test.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/internal/arduino/cores/fqbn_test.go b/internal/arduino/cores/fqbn_test.go index 5c4cd9836f8..53200cabaca 100644 --- a/internal/arduino/cores/fqbn_test.go +++ b/internal/arduino/cores/fqbn_test.go @@ -155,3 +155,18 @@ func TestMatch(t *testing.T) { require.False(t, b.Match(a)) } } + +func TestValidCharacters(t *testing.T) { + // These FQBNs contain valid characters + validFqbns := []string{"ardui_no:av_r:un_o", "arduin.o:av.r:un.o", "arduin-o:av-r:un-o", "arduin-o:av-r:un-o:a=b=c=d"} + for _, fqbn := range validFqbns { + _, err := ParseFQBN(fqbn) + require.NoError(t, err) + } + // These FQBNs contain invalid characters + invalidFqbns := []string{"arduin-o:av-r:un=o", "arduin?o:av-r:uno", "arduino:av*r:uno"} + for _, fqbn := range invalidFqbns { + _, err := ParseFQBN(fqbn) + require.Error(t, err) + } +}