This is an automated email from the ASF dual-hosted git repository. sjanc pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/mynewt-newt.git
commit 55642e1c4dc9000e951eb03e4f90c547b493cb97 Author: Szymon Janc <[email protected]> AuthorDate: Mon Oct 19 17:46:37 2026 +0200 newt/syscfg: Reject empty pieces in range restrictions A range restriction with an empty piece or a missing bound, e.g. "0..1,", "1,,3", "..5" or "", was accepted and turned into an expression containing empty parentheses, "((X) == ())", which crashed newt when evaluated. Reject empty range pieces and missing lower/upper bounds with an error naming the setting and the full range expression. Assisted-by: Claude:claude-opus-5-5 --- newt/syscfg/restrict.go | 11 ++++-- newt/syscfg/restrict_test.go | 86 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+), 3 deletions(-) diff --git a/newt/syscfg/restrict.go b/newt/syscfg/restrict.go index 6c70498a..84e92cc0 100644 --- a/newt/syscfg/restrict.go +++ b/newt/syscfg/restrict.go @@ -359,13 +359,18 @@ func createRangeRestriction(baseSetting string, expr string) (CfgRestriction, er rtoken := CfgRestrictionRange{} limits := strings.Split(token, "..") - if len(limits) == 1 { + for i := range limits { + limits[i] = strings.TrimSpace(limits[i]) + } + if len(limits) == 1 && limits[0] != "" { rtoken.LExpr = limits[0] - } else if len(limits) == 2 && len(strings.TrimSpace(limits[1])) > 0 { + } else if len(limits) == 2 && limits[0] != "" && limits[1] != "" { rtoken.LExpr = limits[0] rtoken.RExpr = limits[1] } else { - return r, util.FmtNewtError("invalid token in range expression \"%s\"", token) + return r, util.FmtNewtError( + "invalid token \"%s\" in range expression \"%s\" "+ + "for setting %s", token, expr, baseSetting) } r.Ranges = append(r.Ranges, rtoken) diff --git a/newt/syscfg/restrict_test.go b/newt/syscfg/restrict_test.go new file mode 100644 index 00000000..502ef9c4 --- /dev/null +++ b/newt/syscfg/restrict_test.go @@ -0,0 +1,86 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package syscfg + +import ( + "strings" + "testing" + + "mynewt.apache.org/newt/newt/cfgv" +) + +func TestCreateRangeRestrictionInvalid(t *testing.T) { + exprs := []string{ + "", + " ", + "0..1,", + ",0..1", + "1,,3", + "..5", + "5..", + "1..2..3", + "1.. ,3", + } + for _, expr := range exprs { + _, err := createRangeRestriction("FOO", expr) + if err == nil { + t.Errorf("expected error for range \"%s\"", expr) + continue + } + if !strings.Contains(err.Error(), "FOO") { + t.Errorf("error for range \"%s\" does not name setting: %s", + expr, err.Error()) + } + } +} + +func TestCreateRangeRestrictionValid(t *testing.T) { + tests := []struct { + expr string + val string + met bool + }{ + {"0..10", "5", true}, + {"0..10", "11", false}, + {"0..1, 5", "5", true}, + {" 0 .. 1 , 5 ", "4", false}, + {"1,2,3", "2", true}, + {"MIN..MAX", "7", true}, + } + for _, tc := range tests { + r, err := createRangeRestriction("FOO", tc.expr) + if err != nil { + t.Errorf("unexpected error for range \"%s\": %v", tc.expr, err) + continue + } + + cfg := NewCfg() + cfg.Settings["FOO"] = CfgEntry{Name: "FOO", Value: tc.val} + settings := cfgv.NewSettingsFromMap(map[string]string{ + "FOO": tc.val, + "MIN": "3", + "MAX": "8", + }) + if met := cfg.restrictionMet(r, settings); met != tc.met { + t.Errorf("range \"%s\" value %s: got %v, want %v", + tc.expr, tc.val, met, tc.met) + } + } +}
