Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions cmd/mapcidr/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bufio"
"bytes"
"errors"
"fmt"
"net"
"os"
"sort"
Expand Down Expand Up @@ -55,6 +56,7 @@ type Options struct {
SortAscending bool
SortDescending bool
Count bool
Range bool
FilterIP4 bool
FilterIP6 bool
ToIP4 bool
Expand Down Expand Up @@ -119,6 +121,7 @@ func ParseOptions() *Options {
flagSet.BoolVarP(&options.Aggregate, "aggregate", "a", false, "Aggregate IPs/CIDRs into minimum subnet"),
flagSet.BoolVarP(&options.AggregateApprox, "aggregate-approx", "aa", false, "Aggregate sparse IPs/CIDRs into minimum approximated subnet"),
flagSet.BoolVarP(&options.Count, "count", "c", false, "Count number of IPs in given CIDR"),
flagSet.BoolVarP(&options.Range, "range", "r", false, "Convert CIDR to IP range (e.g. 192.168.0.0-192.168.255.255)"),
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

--range can be silently ignored with other processing flags.
process() only calls commonFunc() on specific paths; with flags like --aggregate, --shuffle-ip, --sort, --count, etc., --range won’t execute and no error is raised. Please fail fast on incompatible combinations in validateOptions().

Proposed guard in validateOptions()
 func (options *Options) validateOptions() error {
@@
 	if options.ToIP4 && options.ToIP6 {
 		return errors.New("IP4 and IP6 can't be converted together")
 	}
+
+	if options.Range && (options.Aggregate || options.AggregateApprox || options.Shuffle ||
+		options.SortAscending || options.SortDescending || options.Count ||
+		options.Slices > 0 || options.HostCount > 0) {
+		return errors.New("range can't be used with aggregate/aggregate-approx/shuffle/sort/count/sbc/sbh")
+	}
+
 	if options.FilterIP != nil && options.MatchIP != nil {
 		return errors.New("both match and filter mode specified")
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cmd/mapcidr/main.go` at line 124, The --range flag (options.Range) can be
silently ignored because process() only invokes commonFunc() on certain
branches; add a compatibility guard in validateOptions() to detect when
options.Range is true together with mutually incompatible flags (e.g.,
--aggregate, --shuffle-ip, --sort, --count) and return an error (or non-zero
exit) so the program fails fast; update validateOptions() to list the
conflicting flags, check their values, and surface a clear error message
referencing --range and the conflicting flag(s) so callers know to remove the
incompatible combination.

flagSet.BoolVarP(&options.ToIP4, "to-ipv4", "t4", false, "Convert IPs to IPv4 format"),
flagSet.BoolVarP(&options.ToIP6, "to-ipv6", "t6", false, "Convert IPs to IPv6 format"),
flagSet.StringSliceVarP(&options.IPFormats, "if", "ip-format", nil, "IP formats (0,1,2,3,4,5,6,7,8,9,10,11)", goflags.NormalizedStringSliceOptions),
Expand Down Expand Up @@ -584,6 +587,18 @@ The purpose of the function is split into subnets or split by no. of host or CID
This gives us benefit of DRY and we can add new features here going forward.
*/
func commonFunc(cidr string, outputchan chan string) {
if options.Range {
_, network, err := net.ParseCIDR(cidr)
if err != nil {
gologger.Fatal().Msgf("%s\n", err)
}
firstIP, lastIP, err := mapcidr.AddressRange(network)
if err != nil {
gologger.Fatal().Msgf("%s\n", err)
}
outputchan <- fmt.Sprintf("%s-%s", firstIP, lastIP)
return
}
if options.Slices > 0 {
subnets, err := mapcidr.SplitN(cidr, options.Slices)
if err != nil {
Expand Down
Loading