{"record":{"id":"fa1958b177d98ba3","repo":"lionsoul2014/ip2region","slug":"length-of-the-two-ips-are-not-the-same","errorCode":null,"errorMessage":"length of the two ips are not the same","messagePattern":"length of the two ips are not the same","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"binding/golang/xdb/util.go","lineNumber":88,"sourceCode":"\nfunc IPSubOne(ip []byte) []byte {\n\tvar r = make([]byte, len(ip))\n\tcopy(r, ip)\n\tfor i := len(ip) - 1; i >= 0; i-- {\n\t\tif r[i] != 0 { // No borrow needed\n\t\t\tr[i]--\n\t\t\tbreak\n\t\t}\n\t\tr[i] = 0xFF // borrow from the next byte\n\t}\n\n\treturn r\n}\n\n// IPAdd Add the spcecified two byte ip\nfunc IPAdd(sip, eip []byte) ([]byte, error) {\n\tif len(sip) != len(eip) {\n\t\treturn []byte{}, fmt.Errorf(\"length of the two ips are not the same\")\n\t}\n\n\tvar carry uint16 = 0\n\tvar result = make([]byte, len(sip)+1)\n\n\tfor i := len(sip) - 1; i >= 0; i-- {\n\t\tsum := uint16(sip[i]) + uint16(eip[i]) + carry\n\t\tresult[i+1] = byte(sum) // Store standard 8-bit result\n\t\tcarry = sum >> 8        // Extract the 1-bit carry for the next byte\n\t}\n\n\t// check and append the carry\n\tif carry > 0 {\n\t\tresult[0] = byte(carry)\n\t\treturn result, nil\n\t} else {\n\t\treturn result[1:], nil\n\t}","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/lionsoul2014/ip2region/blob/c1a1fc7d5941760db3f8431dc05c48cf7f0e30a1/binding/golang/xdb/util.go#L70-L106","documentation":"IPAdd adds two fixed-length byte-encoded IP values and requires both inputs to be the same length (4 or 16 bytes). Mismatched lengths mean one operand is IPv4 and the other IPv6, which cannot be added, so it fails fast.","triggerScenarios":"Calling IPAdd (directly or via IPMiddle) with a 4-byte slice and a 16-byte slice, e.g. mixing results of ParseIP for \"1.2.3.4\" and \"::1\"; computing a middle IP across a range that spans v4 and v6.","commonSituations":"Data files containing both IPv4 and IPv6 rows iterated with a single range-math routine; user-supplied start/end pairs of different families; code that assumed all IPs are 16 bytes after To16 conversion on one side only.","solutions":["Ensure both operands come from the same family: convert both with To4 or both with To16 before calling IPAdd","Reject or skip range pairs whose lengths differ in your data-processing loop","Use IPMiddle only within a single IP version's ranges","Normalize inputs via xdb.ParseIP so both sides get consistent encoding"],"exampleFix":"// before\na, _ := xdb.ParseIP(\"1.2.3.4\")     // 4 bytes\nb, _ := xdb.ParseIP(\"::2\")        // 16 bytes\nm, err := xdb.IPAdd(a, b)          // length mismatch\n// after\nif len(a) != len(b) { return fmt.Errorf(\"mixed ip families\") }\na16 := net.IP(a).To16()\nb16 := net.IP(b).To16()\nm, err := xdb.IPAdd(a16, b16)","handlingStrategy":"type-guard","validationCode":"func sameFamily(a, b []byte) bool { return len(a) == len(b) }","typeGuard":"func canIPAdd(sip, eip []byte) bool {\n    return (len(sip) == 4 || len(sip) == 16) && len(sip) == len(eip)\n}","tryCatchPattern":"r, err := xdb.IPAdd(sip, eip)\nif err != nil {\n    return fmt.Errorf(\"ip add across families (%d vs %d bytes): %w\", len(sip), len(eip), err)\n}","preventionTips":["Normalize all IPs to a fixed width (To16) before any range math","Filter mixed v4/v6 range pairs out of batch jobs before processing","Derive both operands of a pair from the same ParseIP call chain"],"tags":["go","ip-address","argument-validation"],"backgroundTag":"ip-length-mismatch","analyzedSha":"c1a1fc7d5941760db3f8431dc05c48cf7f0e30a1","analyzedAt":"2026-09-02T16:58:39.988Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T21:17:11.164Z"}