8

I'm stuck trying to parse IP addresses from a API result where each of the four pats of the IPv4 Address comes prefixed with 0 (zeroes). Something like this:

127.000.000.001 instead of 127.0.0.1

I started getting parse errors when trying to parse 192.168.001.009. It also fails for 192.168.001.008, but works for 007, 006, 005 up to 001!!!

It also fails for 192.168.001.018, but works for .017, .016 down to 010!

It works for 192.168.001.8 or .8 and also 192.168.001.18 and .19...

Is this a bug in the CLR? Or am I missing something stupid?

Just try:

IPAddress.Parse("192.168.001.007"); // works
IPAddress.Parse("192.168.001.87"); // works
IPAddress.Parse("192.168.001.008"); // throws exception
IPAddress.Parse("192.168.001.19"); // works
IPAddress.Parse("192.168.001.019");  // throws exception
// and so on!
Loudenvier
  • 8,362
  • 6
  • 45
  • 66
  • What exception is thrown? – Bob Kaufman Oct 08 '15 at 22:42
  • Can you simply replace .00 with . - as a workaround? – Grantly Oct 08 '15 at 22:42
  • I have seen this mess up other properties of IpAddress such as telling you 127.000.000.001 is not local host. So I preformat all strings that are obviously 4 octets dotted with 255 or less for each number. ONE CAVEAT there is an IPV6 notation out there that has valid 4 octet ipv4 within it. So you can not do a simple replace on your string input, you have to make sure it is only an ipV4 address and not a ipv6 with an ipv4 part. – Sql Surfer Oct 08 '15 at 22:55

2 Answers2

16

The numbers, since they are starting with 0, are being interpreted as octal instead of decimal. These are not C# literals, so it's up to the library to interpret it one way or another.

A simple way to test it would be to construct an IP ending in ".010", parse it, and you'll see that it was parsed as an ip ending in .8.

A possible quick and dirty solution would be to search for the regex /\.0*/ and replace it with "."

You can find more information on the wikipedia entry for Dot-decimal-notation:

A popular implementation of IP networking, originating in 4.2BSD, contains a function inet_aton() for converting IP addresses in character strings representation to internal binary storage. In addition to the basic four-decimals format and full 32-bit addresses, it also supported intermediate syntaxes of octet.24bits (e.g. 10.1234567; for Class A addresses) and octet.octet.16bits (e.g. 172.16.12345; for Class B addresses). It also allowed the numbers to be written in hexadecimal and octal, by prefixing them with 0x and 0, respectively. These features continue to be supported by software until today, even though they are seen as non-standard. But this also means addresses where an IP address component is written with a leading zero digit may be interpreted differently by different programs: some will ignore the leading zero, some will interpret the number as octal.

Loudenvier
  • 8,362
  • 6
  • 45
  • 66
Pablo Fernandez
  • 279,434
  • 135
  • 377
  • 622
  • That's what I was thinking as well, but according to http://stackoverflow.com/questions/4247037/octal-equivalent-in-c-sharp c# doesn't know about octal - and no compiler available here to test it. – fvu Oct 08 '15 at 22:44
  • @fvu: The `Parse` function is part of the .NET library and not specific to any particular language (shared between C#, F#, C++/CLI, VB.NET, etc, etc) – Ben Voigt Oct 08 '15 at 22:44
  • @fvu: I suspect the IP parsing falls back to WinSock functions which are C based and do recognize octal numbers. – wilx Oct 08 '15 at 22:44
  • @BenVoigt I hadn't considered that. But any way you look at it, this looks like a serious issue in `IPAddress.Parse` – fvu Oct 08 '15 at 22:50
  • It is indeed interpreting it as octal: 192.168.001.010 = 192.168.1.8... Hit the nail in the head Pablo! – Loudenvier Oct 08 '15 at 23:00
  • 1
    I strongly believe this is a bug though. It shouldn't interpret it as octal. I'll have to write my own parsing method which will "sanitize" these IP entries. – Loudenvier Oct 08 '15 at 23:01
  • @Loudenvier that's not a bug ; looking at the source code we can clearly see that a internal method distinguish input between decimal/octal/hex – Sehnsucht Oct 08 '15 at 23:15
  • 2
    @Sehnsucht if you tell me one single valid use case of parsing an IP string using octal values for the "parts" of the ip adress I'll concede the point :-) Not even the documentation mentions it! – Loudenvier Oct 08 '15 at 23:28
  • @Sehnsucht I'll concede it is not a bug, just a bad decision: "A popular implementation of IP networking, originating in 4.2BSD ... also allowed the numbers to be written in hexadecimal and octal, by prefixing them with 0x and 0, respectively. These features continue to be supported by software until today, even though they are seen as non-standard. But this also means addresses where an IP address component is written with a leading zero digit may be interpreted differently by different programs: some will ignore the leading zero, some will interpret the number as octal." – Loudenvier Oct 08 '15 at 23:36
  • @pupeno Just following up on that quick and dirty regex provided... A more correct regex pattern would be `\.0+(?=\d)` - dot followed by one or more zeroes with look-ahead for a digit. Use it like this in C#: `Regex.Replace(ipString, @"\.0+(?=\d)", ".")`. The provided example in the answer removed zeroes in cases like 192.168.0.1, rendering the address invalid. – Emanuel Strömgren Mar 23 '20 at 13:58
6

This is probably because 00X or 0XY are considered octal numbers which allows only digits 0 through 7. Digits 8 and 9 are an error.

wilx
  • 17,697
  • 6
  • 59
  • 114