Inet:getaddr/2 possible bug?

> inet:getaddr( "50.1.1.1", inet ).
{ok,{50,1,1,1}}

> inet:getaddr( "50.001.001.001", inet ).
{ok,{50,1,1,1}}

> inet:getaddr( "2.001.001.001", inet ).
{ok,{2,1,1,1}}

(> inet:getaddr( "002.001.001.001", inet ).
{ok,{2,1,1,1}}

HOWEVER:

> inet:getaddr( "050.001.001.001", inet ).
{ok,{40,1,1,1}}

WHY?!

I guess, as 050 starts with a 0, octal is being used. 50 octal is 40 decimal.

5 Likes

Following up, here is an easily readable explanation:

Thank you for a quick feedback.

Valid IP addresses necessarily need not look β€œvalid”. IP addresses can be represented in idefinitely different ways, therefore it cannot be determined if a value is an IP address or not.

Not sure if the above statement has any bearing to this problem. It is clear that inet module can establish if something is valid IP address or not.

For example:

(0) inet:getaddr( β€œ375.001.001.001”, inet ).

{error,nxdomain}

inet:getaddr( β€œgoogle.com”, inet ).

{ok,{142,251,47,174}}

inet:getaddr( β€œgoogle.comx”, inet ).

{error,nxdomain}

If I were to speculate, I’d say that whenever something does not look as β€œdot-IPv4" address, inet attempts to resolve it via DNS lookup.

The problem is that (under some circumstances) inet module β€œinvents” values for a valid β€œdot-IP Address”.

For example:

(A1) inet:getaddr( β€œ50.1.1.1”, inet ).

{ok,{50,1,1,1}}

and

(A2) inet:getaddr( β€œ050.001.001.001”, inet ).

{ok,{40,1,1,1}}

Should be considered as equivalents, however, (A2) for some reason converts β€œ050” to 40!

A similar behaviour is exhibited wherever the β€œmiddle” digit is preceded by a leading zero, but itself is not a zero (as in β€œ5” in β€œ050”):

(B1) inet:getaddr( β€œ001.001.001.050”, inet ).

{ok,{1,1,1,40}}

B1) inet:getaddr( β€œ001.001.050.001”, inet ).

{ok,{1,1,40, 1}}

etc.

Worse Yet

(C1) inet:getaddr( β€œ050.001.001.001”, inet ).

{ok,{40,1,1,1}}

(C2) inet:getaddr( β€œ040.001.001.001”, inet ).

{ok,{32,1,1,1}}

(C3) inet:getaddr( β€œ030.001.001.001”, inet ).

{ok,{24,1,1,1}}

(C4) inet:getaddr( β€œ020.001.001.001”, inet ).

{ok,{16,1,1,1}}

(C5) inet:getaddr( β€œ010.001.001.001”, inet ).

{ok,{8,1,1,1}}

(C6) inet:getaddr( β€œ000.001.001.001”, inet ).

{ok,{0,1,1,1}}

The above case (C1) reduces the original value by 10; (C2) by 8; (C3) by 6; (C4) by 4 and (C5) by 2, and (C6) by 0, thus returns a correct value.

But then, even that is not done consistently:

inet:getaddr( β€œ57.001.001.001”, inet ).

{ok,{57,1,1,1}}

inet:getaddr( β€œ057.001.001.001”, inet ).

{ok,{47,1,1,1}}

inet:getaddr( β€œ58.001.001.001”, inet ).

{ok,{58,1,1,1}}

inet:getaddr( β€œ058.001.001.001”, inet ).

{error,nxdomain}

Or:

inet:getaddr( β€œ1.001.001.57”, inet ).

{ok,{1,1,1,57}}

inet:getaddr( β€œ1.001.001.057”, inet ).

{ok,{1,1,1,47}}

inet:getaddr( β€œ1.001.001.58”, inet ).

{ok,{1,1,1,58}}

inet:getaddr( β€œ1.001.001.058”, inet ).

{error,nxdomain}

It seems to me like an optimisation that went wrong somewhere.

Go figure, but clearly a bug.

Kind regards

V/

It’s perfectly consistent, anything prefixed by 0 is interpreted as octal. 057 is valid octal, 058 is not, hence 1.001.001.058 gets interpreted as a domain name while 050.001.001.001 gets interpreted as 40.1.1.1 (50 in octal is 40 decimal).

Read the article @mworrell linked :slight_smile:

1 Like

The error here is that β€œ058” can’t ever be a valid octal number, because there is a number greater than 7 in the string. See also:

> 8#56.
46
> 8#57.
47
> 8#58.
* 1:4: syntax error before: 8
> 8#60.
48

Hope this helps.

Good point – I’ve completely forgotten that β€˜0’ prefix is used to specify base 8.

Your explanation is consistent with behaviour I’ve observed.

BTW: Also, if I call inet:getaddr( "0375.98.0xfe.3", inet ).
I get back:
{ok,{253,98,254,3}}

Which is consistent but not terribly useful.

Thanks a lot.

Thanks.

Sorry – I did not see the linked article. Only when it was pointed out to me.
Thanks a lot.

1 Like