Skip to content

Commit 7b5a22a

Browse files
d-a-vper1234silvanocerza
committed
Fix compile command panicking if invalid build.options.json is found (#1118)
* check whether prevOpts is nil in WipeoutBuildPathIfBuildOptionsChanged's Run * + debug message * update from review: improve user message * fix per review * add check to buildOptionsJson too * panic'ing instead of keeping on with mess * fix use of a constant Co-authored-by: per1234 <[email protected]> * [skip changelog] Add compile with invalid build.options.json test Co-authored-by: per1234 <[email protected]> Co-authored-by: Silvano Cerza <[email protected]>
1 parent 9322145 commit 7b5a22a

File tree

3 files changed

+38
-4
lines changed

3 files changed

+38
-4
lines changed

Diff for: legacy/builder/constants/constants.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,9 @@ const MSG_ERROR_ARCHIVING_CORE_CACHE = "Error archiving built core (caching) in
8686
const MSG_CORE_CACHE_UNAVAILABLE = "Unable to cache built core, please tell {0} maintainers to follow https://arduino.github.io/arduino-cli/latest/platform-specification/#recipes-to-build-the-corea-archive-file"
8787
const MSG_BOARD_UNKNOWN = "Board {0} (platform {1}, package {2}) is unknown"
8888
const MSG_BOOTLOADER_FILE_MISSING = "Bootloader file specified but missing: {0}"
89-
const MSG_BUILD_OPTIONS_CHANGED = "Build options changed, rebuilding all"
89+
const MSG_REBUILD_ALL = ", rebuilding all"
90+
const MSG_BUILD_OPTIONS_CHANGED = "Build options changed"
91+
const MSG_BUILD_OPTIONS_INVALID = "{0} invalid"
9092
const MSG_CANT_FIND_SKETCH_IN_PATH = "Unable to find {0} in {1}"
9193
const MSG_FQBN_INVALID = "{0} is not a valid fully qualified board name. Required format is targetPackageName:targetPlatformName:targetBoardName."
9294
const MSG_SKIP_PRECOMPILED_LIBRARY = "Skipping dependencies detection for precompiled library {0}"

Diff for: legacy/builder/wipeout_build_path_if_build_options_changed.go

+9-3
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,15 @@ func (s *WipeoutBuildPathIfBuildOptionsChanged) Run(ctx *types.Context) error {
4040
previousBuildOptionsJson := ctx.BuildOptionsJsonPrevious
4141

4242
var opts *properties.Map
43+
if err := json.Unmarshal([]byte(buildOptionsJson), &opts); err != nil || opts == nil {
44+
panic(constants.BUILD_OPTIONS_FILE + " is invalid")
45+
}
46+
4347
var prevOpts *properties.Map
44-
json.Unmarshal([]byte(buildOptionsJson), &opts)
45-
json.Unmarshal([]byte(previousBuildOptionsJson), &prevOpts)
48+
if err := json.Unmarshal([]byte(previousBuildOptionsJson), &prevOpts); err != nil || prevOpts == nil {
49+
ctx.GetLogger().Println(constants.LOG_LEVEL_DEBUG, constants.MSG_BUILD_OPTIONS_INVALID + constants.MSG_REBUILD_ALL, constants.BUILD_OPTIONS_FILE)
50+
return doCleanup(ctx.BuildPath)
51+
}
4652

4753
// If SketchLocation path is different but filename is the same, consider it equal
4854
if filepath.Base(opts.Get("sketchLocation")) == filepath.Base(prevOpts.Get("sketchLocation")) {
@@ -73,7 +79,7 @@ func (s *WipeoutBuildPathIfBuildOptionsChanged) Run(ctx *types.Context) error {
7379
func doCleanup(buildPath *paths.Path) error {
7480
// FIXME: this should go outside legacy and behind a `logrus` call so users can
7581
// control when this should be printed.
76-
// logger.Println(constants.LOG_LEVEL_INFO, constants.MSG_BUILD_OPTIONS_CHANGED)
82+
// logger.Println(constants.LOG_LEVEL_INFO, constants.MSG_BUILD_OPTIONS_CHANGED + constants.MSG_REBUILD_ALL)
7783

7884
if files, err := buildPath.ReadDir(); err != nil {
7985
return errors.WithMessage(err, "cleaning build path")

Diff for: test/test_compile.py

+26
Original file line numberDiff line numberDiff line change
@@ -1021,3 +1021,29 @@ def test_compile_with_conflicting_libraries_include(run_command, data_dir, copy_
10211021
assert 'Multiple libraries were found for "OneWire.h"' in lines
10221022
assert f"Used: {one_wire_lib_path}" in lines
10231023
assert f"Not used: {one_wire_ng_lib_path}" in lines
1024+
1025+
1026+
def test_compile_with_invalid_build_options_json(run_command, data_dir):
1027+
assert run_command("update")
1028+
1029+
assert run_command("core install arduino:[email protected]")
1030+
1031+
sketch_name = "CompileInvalidBuildOptionsJson"
1032+
sketch_path = Path(data_dir, sketch_name)
1033+
fqbn = "arduino:avr:uno"
1034+
1035+
# Create a test sketch
1036+
assert run_command(f"sketch new {sketch_path}")
1037+
1038+
# Get the build directory
1039+
sketch_path_md5 = hashlib.md5(bytes(sketch_path)).hexdigest().upper()
1040+
build_dir = Path(tempfile.gettempdir(), f"arduino-sketch-{sketch_path_md5}")
1041+
1042+
assert run_command(f"compile -b {fqbn} {sketch_path} --verbose")
1043+
1044+
# Breaks the build.options.json file
1045+
build_options_json = build_dir / "build.options.json"
1046+
with open(build_options_json, "w") as f:
1047+
f.write("invalid json")
1048+
1049+
assert run_command(f"compile -b {fqbn} {sketch_path} --verbose")

0 commit comments

Comments
 (0)