Skip to content

Commit fe8ce39

Browse files
author
Luca Bianconi
committed
fix: validate sketch name
1 parent 1962996 commit fe8ce39

File tree

2 files changed

+88
-0
lines changed

2 files changed

+88
-0
lines changed

Diff for: commands/sketch/new.go

+17
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package sketch
1818
import (
1919
"context"
2020
"errors"
21+
"regexp"
2122

2223
"github.com/arduino/arduino-cli/arduino"
2324
"github.com/arduino/arduino-cli/arduino/globals"
@@ -34,6 +35,9 @@ void loop() {
3435
}
3536
`)
3637

38+
var sketchNameValidationRegex = regexp.MustCompile(`^([A-Za-z\d]+[_.-]*)+$`)
39+
var sketchNameMaxLength = 63
40+
3741
// NewSketch creates a new sketch via gRPC
3842
func NewSketch(ctx context.Context, req *rpc.NewSketchRequest) (*rpc.NewSketchResponse, error) {
3943
var sketchesDir string
@@ -42,6 +46,19 @@ func NewSketch(ctx context.Context, req *rpc.NewSketchRequest) (*rpc.NewSketchRe
4246
} else {
4347
sketchesDir = configuration.Settings.GetString("directories.User")
4448
}
49+
50+
if len(req.SketchName) > sketchNameMaxLength {
51+
return nil, &arduino.CantCreateSketchError{Cause: errors.New(tr("sketch name too long (%d characters). Maximum allowed length is %d",
52+
len(req.SketchName),
53+
sketchNameMaxLength))}
54+
}
55+
56+
if !sketchNameValidationRegex.MatchString(req.SketchName) {
57+
return nil, &arduino.CantCreateSketchError{Cause: errors.New(tr("invalid sketch name \"%s\". Required pattern %s",
58+
req.SketchName,
59+
sketchNameValidationRegex.String()))}
60+
}
61+
4562
sketchDirPath := paths.New(sketchesDir).Join(req.SketchName)
4663
if err := sketchDirPath.MkdirAll(); err != nil {
4764
return nil, &arduino.CantCreateSketchError{Cause: err}

Diff for: commands/sketch/new_test.go

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package sketch
2+
3+
import (
4+
"context"
5+
"testing"
6+
7+
"github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
8+
"github.com/stretchr/testify/require"
9+
)
10+
11+
func Test_SketchNameWrongPattern(t *testing.T) {
12+
invalidNames := []string{
13+
"&",
14+
"",
15+
".hello",
16+
"_hello",
17+
"-hello",
18+
"hello*",
19+
"||||||||||||||",
20+
",`hack[}attempt{];",
21+
}
22+
for _, name := range invalidNames {
23+
_, err := NewSketch(context.Background(), &commands.NewSketchRequest{
24+
SketchName: name,
25+
SketchDir: t.TempDir(),
26+
})
27+
require.NotNil(t, err)
28+
29+
require.Error(t, err, `Can't create sketch: invalid sketch name "%s". Required pattern %s`,
30+
name,
31+
sketchNameValidationRegex)
32+
}
33+
}
34+
35+
func Test_SketchNameTooLong(t *testing.T) {
36+
tooLongName := make([]byte, sketchNameMaxLength+1)
37+
for i := range tooLongName {
38+
tooLongName[i] = 'a'
39+
}
40+
_, err := NewSketch(context.Background(), &commands.NewSketchRequest{
41+
SketchName: string(tooLongName),
42+
SketchDir: t.TempDir(),
43+
})
44+
require.NotNil(t, err)
45+
46+
require.Error(t, err, `Can't create sketch: sketch name too long (%d characters). Maximum allowed length is %d`,
47+
len(tooLongName),
48+
sketchNameMaxLength)
49+
}
50+
51+
func Test_SketchNameOk(t *testing.T) {
52+
lengthLimitName := make([]byte, sketchNameMaxLength)
53+
for i := range lengthLimitName {
54+
lengthLimitName[i] = 'a'
55+
}
56+
validNames := []string{
57+
"h",
58+
"h.ello",
59+
"h..ello-world",
60+
"h..ello-world.",
61+
"hello_world__",
62+
string(lengthLimitName),
63+
}
64+
for _, name := range validNames {
65+
_, err := NewSketch(context.Background(), &commands.NewSketchRequest{
66+
SketchName: name,
67+
SketchDir: t.TempDir(),
68+
})
69+
require.Nil(t, err)
70+
}
71+
}

0 commit comments

Comments
 (0)