Skip to content

Commit 20e315c

Browse files
authored
fix(builder): strip UTF-8 BOM from .ino sources before preprocessing (#2983)
* fix(builder): strip UTF-8 BOM from .ino sources before preprocessing When a sketch .ino is saved as UTF-8 *with BOM*, the BOM bytes (EF BB BF) reach the compiler and cause: stray '\357' in program stray '\273' in program stray '\277' in program This strips the BOM at read-time so the merged .cpp and copied sources are clean. Refs: arduino/arduino-ide#2752 * test: add unit tests for stripUTF8BOM
1 parent 504b43e commit 20e315c

File tree

2 files changed

+30
-0
lines changed

2 files changed

+30
-0
lines changed

internal/arduino/builder/sketch.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,14 @@ var (
3737
includesArduinoH = regexp.MustCompile(`(?m)^\s*#\s*include\s*[<\"]Arduino\.h[>\"]`)
3838
)
3939

40+
// stripUTF8BOM removes a UTF-8 BOM if present at the start of the file.
41+
func stripUTF8BOM(b []byte) []byte {
42+
if len(b) >= 3 && b[0] == 0xEF && b[1] == 0xBB && b[2] == 0xBF {
43+
return b[3:]
44+
}
45+
return b
46+
}
47+
4048
// prepareSketchBuildPath copies the sketch source files in the build path.
4149
// The .ino files are merged together to create a .cpp file (by the way, the
4250
// .cpp file still needs to be Arduino-preprocessed to compile).
@@ -82,6 +90,7 @@ func (b *Builder) sketchMergeSources(overrides map[string]string) (int, string,
8290
if err != nil {
8391
return "", errors.New(i18n.Tr("reading file %[1]s: %[2]s", f, err))
8492
}
93+
data = stripUTF8BOM(data)
8594
return string(data), nil
8695
}
8796

@@ -136,7 +145,9 @@ func (b *Builder) sketchCopyAdditionalFiles(buildPath *paths.Path, overrides map
136145
if err != nil {
137146
return fmt.Errorf("%s: %w", i18n.Tr("unable to read contents of the source item"), err)
138147
}
148+
s = stripUTF8BOM(s)
139149
sourceBytes = s
150+
140151
}
141152

142153
// tag each additional file with the filename of the source it was copied from

internal/arduino/builder/sketch_test.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,22 @@ func TestCopyAdditionalFiles(t *testing.T) {
106106
require.NoError(t, err)
107107
require.Equal(t, info1.ModTime(), info2.ModTime())
108108
}
109+
110+
func TestStripUTF8BOM(t *testing.T) {
111+
// Case 1: Input with BOM
112+
inputWithBOM := []byte{0xEF, 0xBB, 0xBF, 'H', 'e', 'l', 'l', 'o'}
113+
expected := []byte("Hello")
114+
115+
output := stripUTF8BOM(inputWithBOM)
116+
require.Equal(t, expected, output, "BOM should be stripped")
117+
118+
// Case 2: Input without BOM
119+
inputNoBOM := []byte("Hello")
120+
outputNoBOM := stripUTF8BOM(inputNoBOM)
121+
require.Equal(t, inputNoBOM, outputNoBOM, "Input without BOM should remain unchanged")
122+
123+
// Case 3: Input shorter than 3 bytes (edge case)
124+
shortInput := []byte{0xEF}
125+
outputShort := stripUTF8BOM(shortInput)
126+
require.Equal(t, shortInput, outputShort, "Short input should remain unchanged")
127+
}

0 commit comments

Comments
 (0)