{"record":{"id":"f7baa5ba21d47641","repo":"shadow1ng/fscan","slug":"parser-invalid-ip-range-fmt","errorCode":null,"errorMessage":"parser_invalid_ip_range_fmt","messagePattern":"parser_invalid_ip_range_fmt","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/parsers/host_iterator.go","lineNumber":347,"sourceCode":"\t\treturn nil, fmt.Errorf(\"%s\", i18n.GetText(\"parser_ipv4_only\"))\n\t}\n\tones, bits := ipNet.Mask.Size()\n\tif bits != 32 {\n\t\treturn nil, fmt.Errorf(\"%s\", i18n.GetText(\"parser_ipv4_only\"))\n\t}\n\tsize := uint64(1) << uint(32-ones)\n\tend := start + uint32(size-1)\n\tif size > 2 {\n\t\tstart++\n\t\tend--\n\t}\n\treturn &cidrHostSource{current: start, end: end}, nil\n}\n\nfunc newRangeHostSource(rangeStr string) (hostSource, error) {\n\tparts := strings.Split(rangeStr, \"-\")\n\tif len(parts) != 2 {\n\t\treturn nil, fmt.Errorf(\"%s\", i18n.Tr(\"parser_invalid_ip_range_fmt\", rangeStr))\n\t}\n\n\tstartIPStr := strings.TrimSpace(parts[0])\n\tendIPStr := strings.TrimSpace(parts[1])\n\tstartIP := net.ParseIP(startIPStr)\n\tif startIP == nil {\n\t\treturn nil, fmt.Errorf(\"%s\", i18n.Tr(\"parser_invalid_start_ip\", startIPStr))\n\t}\n\n\tif len(endIPStr) < 4 || !strings.Contains(endIPStr, \".\") {\n\t\tendNum, err := strconv.Atoi(endIPStr)\n\t\tif err != nil || endNum > 255 {\n\t\t\treturn nil, fmt.Errorf(\"%s\", i18n.Tr(\"parser_invalid_ip_end_val\", endIPStr))\n\t\t}\n\t\tparts := strings.Split(startIPStr, \".\")\n\t\tif len(parts) != 4 {\n\t\t\treturn nil, fmt.Errorf(\"%s\", i18n.Tr(\"parser_invalid_ip_fmt\", startIPStr))\n\t\t}","sourceCodeStart":329,"sourceCodeEnd":365,"githubUrl":"https://github.com/shadow1ng/fscan/blob/95cc12e753bf43de7004e5aef42a9ffba3934303/common/parsers/host_iterator.go#L329-L365","documentation":"newRangeHostSource rejects an IP-range string that does not split into exactly two dash-separated parts. The range format is strictly \"startIP-endIP\" (or \"startIP-lastOctet\"); strings like \"1.1.1.1-2-3\", empty strings, or \"1.1.1.1-\" fail strings.Split on \"-\" with a length other than 2 and return this formatted message including the offending range string.","triggerScenarios":"Calling addRange/newHostSource with strings containing more than one dash (e.g. \"10.0.0.1-10.0.0-5\"), no dash at all (e.g. \"10.0.0.1\"), or a trailing dash (\"10.0.0.1-\").","commonSituations":"Users writing hyphenated hostnames or FQDN ranges (\"web-01-web-05\") into an IP-range field; confusion between CIDR notation and range notation; typos with extra dashes copied from spreadsheets.","solutions":["Supply exactly one dash separating a start and end: \"192.168.1.1-192.168.1.50\".","Use the short-tail form \"192.168.1.1-50\" for same-/24 ranges, or CIDR \"192.168.1.0/24\" for whole networks.","Pre-validate with strings.Count(rangeStr, \"-\") == 1 before calling addRange."],"exampleFix":"// before\nm.AddRange(\"10.0.0.1-10.0.0.254-x\") // parser_invalid_ip_range_fmt\n\n// after\nif strings.Count(rng, \"-\") != 1 {\n    return fmt.Errorf(\"range must be start-end: %q\", rng)\n}\nm.AddRange(\"10.0.0.1-10.0.0.254\")","handlingStrategy":"validation","validationCode":"func isWellFormedRange(s string) bool {\n    return strings.Count(s, \"-\") == 1 &&\n        len(strings.TrimSpace(strings.SplitN(s, \"-\", 2)[0])) > 0 &&\n        len(strings.TrimSpace(strings.SplitN(s, \"-\", 2)[1])) > 0\n}","typeGuard":null,"tryCatchPattern":"src, err := newRangeHostSource(rng)\nif err != nil {\n    log.Printf(\"invalid range %q: %v\", rng, err)\n    return nil\n}","preventionTips":["Escape or reject hyphenated hostnames in range fields at the config schema level.","Offer users distinct fields for CIDR vs range notation to avoid format confusion."],"tags":["ip-range","parser","go","format"],"backgroundTag":"invalid-argument-format","analyzedSha":"95cc12e753bf43de7004e5aef42a9ffba3934303","analyzedAt":"2026-09-06T17:07:30.094Z","contentChangedAt":"2026-09-06T17:07:30.094Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}