77 "context"
88 "fmt"
99 "io"
10+ "net"
1011 "os"
1112 "regexp"
1213 "strings"
@@ -337,11 +338,14 @@ func (i *ListInputProvider) initializeInputSources(opts *Options) error {
337338 for _ , target := range options .ExcludeTargets {
338339 switch {
339340 case iputil .IsCIDR (target ):
340- ips := expand .CIDR (target )
341- i .removeTargets (ips )
341+ i .removeTargets ([]string {target })
342342 case asn .IsASN (target ):
343- ips := expand .ASN (target )
344- i .removeTargets (ips )
343+ cidrs , _ := asn .GetCIDRsForASNNum (target )
344+ cidrStrs := make ([]string , 0 , len (cidrs ))
345+ for _ , cidr := range cidrs {
346+ cidrStrs = append (cidrStrs , cidr .String ())
347+ }
348+ i .removeTargets (cidrStrs )
345349 default :
346350 i .Del (options .ExecutionId , target )
347351 }
@@ -500,37 +504,57 @@ func (i *ListInputProvider) setItem(metaInput *contextargs.MetaInput) {
500504 }
501505}
502506
503- // setItem in the kv store
504- func (i * ListInputProvider ) delItem (metaInput * contextargs.MetaInput ) {
505- targetUrl , err := urlutil .ParseURL (metaInput .Input , true )
506- if err != nil {
507- gologger .Warning ().Msgf ("%s\n " , err )
507+ const removeTargetsChunkSize = 5000
508+
509+ // delItem removes all hostMap entries matching any of the given targets in a single scan.
510+ func (i * ListInputProvider ) delItem (targets ... * contextargs.MetaInput ) {
511+ type parsedTarget struct {
512+ host string
513+ regex * regexp.Regexp
514+ }
515+
516+ var parsed []parsedTarget
517+ for _ , mi := range targets {
518+ targetUrl , err := urlutil .ParseURL (mi .Input , true )
519+ if err != nil {
520+ continue
521+ }
522+ re , _ := regexp .Compile (mi .Input )
523+ parsed = append (parsed , parsedTarget {host : targetUrl .Host , regex : re })
524+ }
525+ if len (parsed ) == 0 {
508526 return
509527 }
510528
529+ var keysToDelete []string
511530 i .hostMap .Scan (func (k , _ []byte ) error {
512531 var tmpMetaInput contextargs.MetaInput
513532 if err := tmpMetaInput .Unmarshal (string (k )); err != nil {
514- return err
533+ return nil
515534 }
516535 tmpKey , err := tmpMetaInput .MarshalString ()
517536 if err != nil {
518- return err
537+ return nil
519538 }
520539 tmpUrl , err := urlutil .ParseURL (tmpMetaInput .Input , true )
521540 if err != nil {
522- return err
541+ return nil
523542 }
524-
525- matched , _ := regexp .MatchString (metaInput .Input , tmpUrl .Host )
526- if tmpUrl .Host == targetUrl .Host || matched {
527- _ = i .hostMap .Del (tmpKey )
528- i .excludedHosts [tmpKey ] = struct {}{}
529- i .excludedCount ++
530- i .inputCount --
543+ for _ , pt := range parsed {
544+ if tmpUrl .Host == pt .host || (pt .regex != nil && pt .regex .MatchString (tmpUrl .Host )) {
545+ keysToDelete = append (keysToDelete , tmpKey )
546+ break
547+ }
531548 }
532549 return nil
533550 })
551+
552+ for _ , key := range keysToDelete {
553+ _ = i .hostMap .Del (key )
554+ i .excludedHosts [key ] = struct {}{}
555+ i .excludedCount ++
556+ i .inputCount --
557+ }
534558}
535559
536560// setHostMapStream sets item in stream mode
@@ -548,9 +572,72 @@ func (i *ListInputProvider) addTargets(executionId string, targets []string) {
548572}
549573
550574func (i * ListInputProvider ) removeTargets (targets []string ) {
551- for _ , target := range targets {
552- metaInput := contextargs .NewMetaInput ()
553- metaInput .Input = target
554- i .delItem (metaInput )
575+ var cidrs []* net.IPNet
576+ var otherTargets []string
577+
578+ for _ , t := range targets {
579+ if _ , ipnet , err := net .ParseCIDR (t ); err == nil {
580+ cidrs = append (cidrs , ipnet )
581+ } else {
582+ otherTargets = append (otherTargets , t )
583+ }
584+ }
585+
586+ // CIDR targets: single scan with containment check
587+ if len (cidrs ) > 0 {
588+ var keysToDelete []string
589+ i .hostMap .Scan (func (k , _ []byte ) error {
590+ var mi contextargs.MetaInput
591+ if err := mi .Unmarshal (string (k )); err != nil {
592+ return nil
593+ }
594+ key , err := mi .MarshalString ()
595+ if err != nil {
596+ return nil
597+ }
598+ parsed , err := urlutil .ParseURL (mi .Input , true )
599+ if err != nil {
600+ return nil
601+ }
602+ if matchesCIDR (parsed .Hostname (), cidrs ) || (mi .CustomIP != "" && matchesCIDR (mi .CustomIP , cidrs )) {
603+ keysToDelete = append (keysToDelete , key )
604+ }
605+ return nil
606+ })
607+ for _ , key := range keysToDelete {
608+ _ = i .hostMap .Del (key )
609+ i .excludedHosts [key ] = struct {}{}
610+ i .excludedCount ++
611+ i .inputCount --
612+ }
613+ }
614+
615+ // other targets: chunked delItem with existing hostname+regex matching
616+ for start := 0 ; start < len (otherTargets ); start += removeTargetsChunkSize {
617+ end := start + removeTargetsChunkSize
618+ if end > len (otherTargets ) {
619+ end = len (otherTargets )
620+ }
621+ chunk := otherTargets [start :end ]
622+ metaInputs := make ([]* contextargs.MetaInput , 0 , len (chunk ))
623+ for _ , target := range chunk {
624+ mi := contextargs .NewMetaInput ()
625+ mi .Input = target
626+ metaInputs = append (metaInputs , mi )
627+ }
628+ i .delItem (metaInputs ... )
629+ }
630+ }
631+
632+ func matchesCIDR (host string , cidrs []* net.IPNet ) bool {
633+ ip := net .ParseIP (host )
634+ if ip == nil {
635+ return false
636+ }
637+ for _ , ipnet := range cidrs {
638+ if ipnet .Contains (ip ) {
639+ return true
640+ }
555641 }
642+ return false
556643}
0 commit comments