@@ -175,6 +175,84 @@ func validateTemplate(s string) (outputTemplate, error) {
175175 return outputTemplate (s ), nil
176176}
177177
178+ func validateFilterString (s string ) ([]filter , error ) {
179+ isAlphaNum := func (b byte ) bool {
180+ return (b >= 'a' && b <= 'z' ) ||
181+ (b >= 'A' && b <= 'Z' ) ||
182+ (b >= '0' && b <= '9' )
183+ }
184+
185+ var out []filter
186+
187+ i := 0
188+ for i < len (s ) {
189+ start := i
190+
191+ // parse GOOS
192+ osStart := i
193+ if i < len (s ) {
194+ if s [i ] == '*' {
195+ i ++
196+ } else {
197+ for i < len (s ) && isAlphaNum (s [i ]) {
198+ i ++
199+ }
200+ }
201+ }
202+ if osStart == i {
203+ return nil , fmt .Errorf ("at %d: expected GOOS" , i )
204+ }
205+ if i >= len (s ) || s [i ] != '/' {
206+ if i < len (s ) {
207+ return nil , fmt .Errorf ("at %d: unexpected character: %c" , i , s [i ])
208+ }
209+ return nil , fmt .Errorf ("at %d: expected '/'" , i )
210+ }
211+ goos := s [osStart :i ]
212+ i ++ // skip '/'
213+
214+ // parse GOARCH
215+ archStart := i
216+ if i < len (s ) {
217+ if s [i ] == '*' {
218+ i ++
219+ } else {
220+ for i < len (s ) && isAlphaNum (s [i ]) {
221+ i ++
222+ }
223+ }
224+ }
225+ if archStart == i {
226+ return nil , fmt .Errorf ("at %d: expected GOARCH" , i )
227+ }
228+ goarch := s [archStart :i ]
229+
230+ out = append (out , filter (fmt .Sprintf ("%s/%s" , goos , goarch )))
231+
232+ // end or comma
233+ if i == len (s ) {
234+ break
235+ }
236+
237+ if s [i ] != ',' {
238+ return nil , fmt .Errorf ("at %d: unexpected character: %c" , i , s [i ])
239+ }
240+ i ++ // skip ','
241+
242+ if i == len (s ) {
243+ return nil , fmt .Errorf ("at %d: trailing comma" , i - 1 )
244+ }
245+
246+ _ = start
247+ }
248+
249+ if len (out ) == 0 {
250+ return nil , fmt .Errorf ("empty filter list" )
251+ }
252+
253+ return out , nil
254+ }
255+
178256// Reads from 'io' on behalf of a path, and returns parsed options.
179257func scanBuildPath (reader io.Reader , path string ) (options , error ) {
180258 var opts options
@@ -204,18 +282,22 @@ func scanBuildPath(reader io.Reader, path string) (options, error) {
204282 if dlog {
205283 log .Printf ("Found include: %s:%d: %s" , path , i , line )
206284 }
207- rest := strings .Split (strings .TrimPrefix (line , "//go:multibuild:include=" ), "," )
208- for _ , v := range rest {
209- opts .Include = append (opts .Include , filter (v ))
285+ rest := strings .TrimPrefix (line , "//go:multibuild:include=" )
286+ filters , err := validateFilterString (rest )
287+ if err != nil {
288+ return options {}, fmt .Errorf ("%s:%d: go:multibuild:include=%s is invalid: %s" , path , i , rest , err )
210289 }
290+ opts .Include = filters
211291 } else if strings .HasPrefix (line , "//go:multibuild:exclude=" ) {
212292 if dlog {
213293 log .Printf ("Found exclude: %s:%d: %s" , path , i , line )
214294 }
215- rest := strings .Split (strings .TrimPrefix (line , "//go:multibuild:exclude=" ), "," )
216- for _ , v := range rest {
217- opts .Exclude = append (opts .Exclude , filter (v ))
295+ rest := strings .TrimPrefix (line , "//go:multibuild:exclude=" )
296+ filters , err := validateFilterString (rest )
297+ if err != nil {
298+ return options {}, fmt .Errorf ("%s:%d: go:multibuild:exclude=%s is invalid: %s" , path , i , rest , err )
218299 }
300+ opts .Exclude = filters
219301 } else {
220302 return options {}, fmt .Errorf ("%s:%d: bad go:multibuild instruction: %q" , path , i , line )
221303 }
0 commit comments