go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/lucicfg/path.go (about) 1 // Copyright 2019 The LUCI Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package lucicfg 16 17 import ( 18 "fmt" 19 "path" 20 "strings" 21 22 "go.starlark.net/starlark" 23 ) 24 25 // cleanRelativePath does path.Join and returns an error if 'rel' is absolute or 26 // (if allowDots is false) the resulting path starts with "..". 27 func cleanRelativePath(base, rel string, allowDots bool) (string, error) { 28 if path.IsAbs(rel) { 29 return "", fmt.Errorf("absolute path %q is not allowed", rel) 30 } 31 rel = path.Join(base, rel) 32 if !allowDots && (rel == ".." || strings.HasPrefix(rel, "../")) { 33 return "", fmt.Errorf("path %q is not allowed, must not start with \"../\"", rel) 34 } 35 return rel, nil 36 } 37 38 func init() { 39 // Used in lucicfg.star, strutil.star and validate.star. 40 declNative("clean_relative_path", func(call nativeCall) (starlark.Value, error) { 41 var base starlark.String 42 var path starlark.String 43 var allowDots starlark.Bool 44 if err := call.unpack(3, &base, &path, &allowDots); err != nil { 45 return nil, err 46 } 47 res, err := cleanRelativePath(base.GoString(), path.GoString(), bool(allowDots)) 48 errStr := "" 49 if err != nil { 50 errStr = err.Error() 51 } 52 return starlark.Tuple{starlark.String(res), starlark.String(errStr)}, nil 53 }) 54 }