{"record":{"id":"a30b57b94ebc3735","repo":"shadow1ng/fscan","slug":"parser-invalid-ip-fmt","errorCode":null,"errorMessage":"parser_invalid_ip_fmt","messagePattern":"parser_invalid_ip_fmt","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/parsers/host_iterator.go","lineNumber":364,"sourceCode":"\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}\n\t\tparts[3] = strconv.Itoa(endNum)\n\t\tendIPStr = strings.Join(parts, \".\")\n\t}\n\n\tstart, ok := ipToUint32(startIP)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"%s\", i18n.GetText(\"parser_ipv4_only\"))\n\t}\n\tend, ok := ipToUint32(net.ParseIP(endIPStr))\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"%s\", i18n.Tr(\"parser_invalid_end_ip\", endIPStr))\n\t}\n\tif start > end {\n\t\treturn nil, fmt.Errorf(\"%s\", i18n.GetText(\"parser_start_gt_end\"))\n\t}\n\treturn &cidrHostSource{current: start, end: end}, nil\n}","sourceCodeStart":346,"sourceCodeEnd":382,"githubUrl":"https://github.com/shadow1ng/fscan/blob/95cc12e753bf43de7004e5aef42a9ffba3934303/common/parsers/host_iterator.go#L346-L382","documentation":"When the short-tail branch rewrites the start IP's last octet, it requires the start string to contain exactly four dot-separated octets. If strings.Split(startIPStr, \".\") yields anything other than 4 parts, this formatted message naming the start string is returned. Note startIP already parsed as an IP, so this mainly guards odd canonical forms before octet substitution.","triggerScenarios":"addRange with a start IP that parses but does not have 4 dot-separated labels in its original string form combined with a numeric short tail, e.g. unusual formatting of the start portion in \"ip-tail\" notation.","commonSituations":"Programmatically generated range strings using abbreviated IP forms; localization/formatting layers that mangle dotted-quad strings before they reach addRange.","solutions":["Pass the start IP in standard dotted-quad form, e.g. \"192.168.1.1-50\".","Normalize the string first: verify strings.Count(start, \".\") == 3 before addRange.","Avoid abbreviated IPv4 forms (e.g. \"127.1\") which net.ParseIP may accept but lack four dotted parts."],"exampleFix":"// before\nm.AddRange(\"192.168.1-50\") // ambiguous; may hit parser_invalid_ip_fmt\n\n// after\nm.AddRange(\"192.168.0.1-50\") // full dotted-quad start plus numeric tail","handlingStrategy":"validation","validationCode":"func startIsDottedQuad(rng string) bool {\n    parts := strings.SplitN(rng, \"-\", 2)\n    if len(parts) != 2 {\n        return false\n    }\n    return len(strings.Split(strings.TrimSpace(parts[0]), \".\")) == 4\n}","typeGuard":null,"tryCatchPattern":"if err := matcher.AddRange(rng); err != nil {\n    return fmt.Errorf(\"normalize %q to dotted-quad: %w\", rng, err)\n}","preventionTips":["Always emit canonical dotted-quad IPv4 strings (net.IP.String() of a To4 address).","Reject abbreviated IP forms in input validation."],"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-14T05:17:10.506Z"}