Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2020-05

Return value of StrToHostAddr and StrToHostAddr6 in sockets unit

21 messages · 6 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Noel Duffy

While working with StrToHostAddr and StrToHostAddr6 over the past couple of weeks I've run into issues caused by the functions returning all zero addresses to indicate errors. All-zero addresses are technically valid according to the RFCs, so an all-zero address shouldn't be used as an error sentinel.

E,g:

0.0.0.0
::
::0.0.0.0

Are considered valid if non-routable addresses. libc's inet_pton will successfully parse these.

A simple solution is to add functions to the sockets unit which accept a var record into which the output will be written and which return a boolean to indicate success or failure. E.g,

function inet_pton4(IP: String; var ip4: in_addr): Boolean;
function inet_pton6(IP: String; var ip6: in6_addr): Boolean;

The names I use here are the libc names, which many other languages also use.

Now, StrToHostAddr and StrToHostAddr6 can call the appropriate function, and programs that use those functions won't notice any change. But new code will be able to use the new functions and have an unambiguous answer as to whether the address is valid or not.

The change is quite straightforward to make, and it won't break existing code, so I think it's worthwhile to do.

Any thoughts or opinions on this?

Michael Van Canneyt
to Noel Duffy
Noel Duffy wrote 34 lines
While working with StrToHostAddr and StrToHostAddr6 over the past couple of weeks I've run into issues caused by the functions returning all zero addresses to indicate errors. All-zero addresses are technically valid according to the RFCs, so an all-zero address shouldn't be used as an error sentinel. E,g: 0.0.0.0 :: ::0.0.0.0 Are considered valid if non-routable addresses. libc's inet_pton will successfully parse these. A simple solution is to add functions to the sockets unit which accept a var record into which the output will be written and which return a boolean to indicate success or failure. E.g, function inet_pton4(IP: String; var ip4: in_addr): Boolean; function inet_pton6(IP: String; var ip6: in6_addr): Boolean; The names I use here are the libc names, which many other languages also use. Now, StrToHostAddr and StrToHostAddr6 can call the appropriate function, and programs that use those functions won't notice any change. But new code will be able to use the new functions and have an unambiguous answer as to whether the address is valid or not. The change is quite straightforward to make, and it won't break existing code, so I think it's worthwhile to do. Any thoughts or opinions on this?

I'm all for it, but please use the following names:

function TryStrToHostAddr(IP: String; var ip4: in_addr): Boolean;
function TryStrToHostAddr6(IP: String; var ip6: in6_addr): Boolean;

Rationale for this request:
All conversion calls in sysutils and dateutils use this naming scheme, it's good for consistency.

(and I hate underscores, but that's beside the point ;))

Michael.

Marco van de Voort
to Michael Van Canneyt

Op 2020-05-12 om 12:32 schreef Michael Van Canneyt:

Show quoted text 24 lines
> The names I use here are the libc names, which many other languages > also use. > > Now, StrToHostAddr and StrToHostAddr6 can call the appropriate > function, and programs that use those functions won't notice any > change. But new code will be able to use the new functions and have > an unambiguous answer as to whether the address is valid or not. > > The change is quite straightforward to make, and it won't break > existing code, so I think it's worthwhile to do. > > Any thoughts or opinions on this? I'm all for it, but please use the following names: function TryStrToHostAddr(IP: String; var ip4: in_addr): Boolean; function TryStrToHostAddr6(IP: String; var ip6: in6_addr): Boolean; Rationale for this request: All conversion calls in sysutils and dateutils use this naming scheme, it's good for consistency. (and I hate underscores, but that's beside the point ;))

Yes to the principle and yes to the TryStrTo naming. But I would make the IP param CONST ;-)

Noel Duffy
to Marco van de Voort
Marco van de Voort wrote 28 lines
Op 2020-05-12 om 12:32 schreef Michael Van Canneyt: > >> The names I use here are the libc names, which many other languages >> also use. >> >> Now, StrToHostAddr and StrToHostAddr6 can call the appropriate >> function, and programs that use those functions won't notice any >> change. But new code will be able to use the new functions and have >> an unambiguous answer as to whether the address is valid or not. >> >> The change is quite straightforward to make, and it won't break >> existing code, so I think it's worthwhile to do. >> >> Any thoughts or opinions on this? > > I'm all for it, but please use the following names: > > function TryStrToHostAddr(IP: String; var ip4: in_addr): Boolean; > function TryStrToHostAddr6(IP: String; var ip6: in6_addr): Boolean; > > Rationale for this request: All conversion calls in sysutils and > dateutils use this naming scheme, it's good for consistency. > > (and I hate underscores, but that's beside the point ;)) > Yes to the principle and yes to the TryStrTo naming. But I would make the IP param CONST ;-)

Good idea, and normally I would, but the current implementation of StrToHostAddr (see below) does Delete on IP as it processes it. As it currently stands this function must accept a non-const.

function StrToHostAddr(IP : AnsiString) : in_addr ;
Var
     Dummy : AnsiString;
     I,j,k     : Longint;
     Temp : in_addr;
begin
   strtohostaddr.s_addr:=0;              //:=NoAddress;
   For I:=1 to 4 do
     begin
       If I<4 Then
         begin
           J:=Pos('.',IP);
           If J=0 then
             exit;
           Dummy:=Copy(IP,1,J-1);
           Delete (IP,1,J);
         end
        else
          Dummy:=IP;
       Val (Dummy,k,J);
       array4int(temp.s_addr)[i]:=k;
       If J0 then Exit;
    end;
    strtohostaddr.s_addr:=ntohl(Temp.s_addr);
end;
Noel Duffy
to Michael Van Canneyt: I'm all for it, but please use the following names: function TryStrToHostAddr(IP: String;…

On 12/05/20 10:32 pm, Michael Van Canneyt wrote:> On Tue, 12 May 2020, Noel Duffy via fpc-pascal wrote:>>>> A simple solution is to add functions to the sockets unit which accep

Show quoted text 14 lines
> a var record into which the output will be written and which return a > boolean to indicate success or failure. E.g, > > function inet_pton4(IP: String; var ip4: in_addr): Boolean; > function inet_pton6(IP: String; var ip6: in6_addr): Boolean; > I'm all for it, but please use the following names: function TryStrToHostAddr(IP: String; var ip4: in_addr): Boolean; function TryStrToHostAddr6(IP: String; var ip6: in6_addr): Boolean; Rationale for this request: All conversion calls in sysutils and dateutils use this naming scheme, it's good for consistency.

Sure, I can do that. I will look at creating a patch for this. For your purposes, do you prefer to have a new bug in the bug tracker opened for tracking this change?

(and I hate underscores, but that's beside the point ;))

Uh-oh! (looking at sea of underscores in my Pascal code!) ;)

Christo Crause
to Noel Duffy

On Tue, May 12, 2020 at 11:11 PM Noel Duffy via fpc-pascal <

Show quoted text 6 lines
wrote: Sure, I can do that. I will look at creating a patch for this. For your purposes, do you prefer to have a new bug in the bug tracker opened for tracking this change?

If your patch is related to an existing open bug report then keep updates, discussions etc. under the same report, else the information gets fragmented. A reporter cannot delete his/her own old patches, so just append a version number to a new patch, if the patch completely replace a previous patch, and mention the changes/updates in a comment. In your case something like StrToHostAddr6-v2.patch for an updated patch.

Marc Weustink
to Marco van de Voort: Op 2020-05-12 om 12:32 schreef Michael Van Canneyt: Yes to the principle and yes to the…
Marco van de Voort wrote 28 lines
Op 2020-05-12 om 12:32 schreef Michael Van Canneyt: > >> The names I use here are the libc names, which many other languages >> also use. >> >> Now, StrToHostAddr and StrToHostAddr6 can call the appropriate >> function, and programs that use those functions won't notice any >> change. But new code will be able to use the new functions and have >> an unambiguous answer as to whether the address is valid or not. >> >> The change is quite straightforward to make, and it won't break >> existing code, so I think it's worthwhile to do. >> >> Any thoughts or opinions on this? > > I'm all for it, but please use the following names: > > function TryStrToHostAddr(IP: String; var ip4: in_addr): Boolean; > function TryStrToHostAddr6(IP: String; var ip6: in6_addr): Boolean; > > Rationale for this request: All conversion calls in sysutils and > dateutils use this naming scheme, it's good for consistency. > > (and I hate underscores, but that's beside the point ;)) > Yes to the principle and yes to the TryStrTo naming. But I would make the IP param CONST ;-)

And maybe change the var into an out

Marc

Michael Van Canneyt
to Noel Duffy: On 12/05/20 10:32 pm, Michael Van Canneyt wrote:> On Tue, 12 May 2020, Noel Duffy via…
Noel Duffy wrote 21 lines
On 12/05/20 10:32 pm, Michael Van Canneyt wrote:> On Tue, 12 May 2020, Noel Duffy via fpc-pascal wrote:>>>> A simple solution is to add functions to the sockets unit which accep >> a var record into which the output will be written and which return a >> boolean to indicate success or failure. E.g, >> >> function inet_pton4(IP: String; var ip4: in_addr): Boolean; >> function inet_pton6(IP: String; var ip6: in6_addr): Boolean; >> > > I'm all for it, but please use the following names: > > function TryStrToHostAddr(IP: String; var ip4: in_addr): Boolean; > function TryStrToHostAddr6(IP: String; var ip6: in6_addr): Boolean; > > Rationale for this request: All conversion calls in sysutils and > dateutils use this naming scheme, it's good for consistency. Sure, I can do that. I will look at creating a patch for this. For your purposes, do you prefer to have a new bug in the bug tracker opened for tracking this change?

Always a new issue for new changes. Makes it easier to track where something went wrong if something is wrong.

I have applied and committed your patch and resolved the current bugreport. Your test program went into the testsuite.

Many thanks for your efforts !

Show quoted text 5 lines
> > (and I hate underscores, but that's beside the point ;)) Uh-oh! (looking at sea of underscores in my Pascal code!) ;)

Enjoy the view ;-)

Michael.

Michael Van Canneyt
to Christo Crause: On Tue, May 12, 2020 at 11:11 PM Noel Duffy via fpc-pascal < If your patch is related to…
Christo Crause wrote 14 lines
On Tue, May 12, 2020 at 11:11 PM Noel Duffy via fpc-pascal < > wrote: > Sure, I can do that. I will look at creating a patch for this. For your > purposes, do you prefer to have a new bug in the bug tracker opened for > tracking this change? > If your patch is related to an existing open bug report then keep updates, discussions etc. under the same report, else the information gets fragmented. A reporter cannot delete his/her own old patches, so just append a version number to a new patch, if the patch completely replace a previous patch, and mention the changes/updates in a comment. In your case something like StrToHostAddr6-v2.patch for an updated patch.

That is correct if you want to fix a wrong patch.

But not what you should do for this case, because there are 2 issues: fix existing api, and extend the existing api (a refactor).

So: separate reports, and if so desired add a link in 'related to'.

Michael.

Christo Crause
to Michael Van Canneyt
AM Michael Van Canneyt wrote 27 lines
On Wed, 13 May 2020, Christo Crause via fpc-pascal wrote: > On Tue, May 12, 2020 at 11:11 PM Noel Duffy via fpc-pascal < > > wrote: > >> Sure, I can do that. I will look at creating a patch for this. For your >> purposes, do you prefer to have a new bug in the bug tracker opened for >> tracking this change? >> > > If your patch is related to an existing open bug report then keep updates, > discussions etc. under the same report, else the information gets > fragmented. A reporter cannot delete his/her own old patches, so just > append a version number to a new patch, if the patch completely replace a > previous patch, and mention the changes/updates in a comment. In your case > something like StrToHostAddr6-v2.patch for an updated patch. That is correct if you want to fix a wrong patch. But not what you should do for this case, because there are 2 issues: fix existing api, and extend the existing api (a refactor). So: separate reports, and if so desired add a link in 'related to'.

Apologies, I should probably only comment if I followed all the details of the discussion...

Noel Duffy
to Michael Van Canneyt: Always a new issue for new changes. Makes it easier to track where something went wrong…
Michael Van Canneyt wrote
Always a new issue for new changes. Makes it easier to track where something went wrong if something is wrong.

Done. https://bugs.freepascal.org/view.php?id=37060

I will try to get a patch ready for this in the next couple of days.

BTW, I didn't see an obvious way within Mantis to link one bug to another, or to indicate any kind of relationship. Is this possible? I've just mentioned the bug number in the bug text of the new one so that anyone reading it can see the link.

I have applied and committed your patch and resolved the current bugreport. Your test program went into the testsuite. Many thanks for your efforts !

Excellent. Thanks for that.

Noel Duffy
to Marc Weustink: And maybe change the var into an out Marc
Marc Weustink wrote 19 lines
On 12-5-2020 14:56, Marco van de Voort wrote: > > Op 2020-05-12 om 12:32 schreef Michael Van Canneyt: >> I'm all for it, but please use the following names: >> >> function TryStrToHostAddr(IP: String; var ip4: in_addr): Boolean; >> function TryStrToHostAddr6(IP: String; var ip6: in6_addr): Boolean; >> >> Rationale for this request: All conversion calls in sysutils and >> dateutils use this naming scheme, it's good for consistency. >> >> (and I hate underscores, but that's beside the point ;)) >> > Yes to the principle and yes to the TryStrTo naming. But I would make > the IP param CONST ;-) And maybe change the var into an out

As I've already learned the hard way, the sockets unit is compiled in "fpc" mode, so there's no "out" parameters. Otherwise I would definitely have used one.

Michael Van Canneyt
to Noel Duffy: Done. https://bugs.freepascal.org/view.php?id=37060 I will try to get a patch ready for…
Noel Duffy wrote 13 lines
On 13/05/20 7:26 pm, Michael Van Canneyt wrote: > > Always a new issue for new changes. Makes it easier to track where > something went wrong if something is wrong. Done. https://bugs.freepascal.org/view.php?id=37060 I will try to get a patch ready for this in the next couple of days. BTW, I didn't see an obvious way within Mantis to link one bug to another, or to indicate any kind of relationship. Is this possible? I've just mentioned the bug number in the bug text of the new one so that anyone reading it can see the link.

You can after you saved it, see the 'Relationships' box below the 'Issue Details' box.

I added the relation.

Michael.

Noel Duffy
to Michael Van Canneyt
Michael Van Canneyt wrote 16 lines
On Wed, 13 May 2020, Noel Duffy via fpc-pascal wrote: > On 13/05/20 7:26 pm, Michael Van Canneyt wrote: >> > > BTW, I didn't see an obvious way within Mantis to link one bug to > another, or to indicate any kind of relationship. Is this possible? > I've just mentioned the bug number in the bug text of the new one so > that anyone reading it can see the link. You can after you saved it, see the 'Relationships' box below the 'Issue Details' box. I added the relation.

I see the box now. But it appears I can't add anything to it. Maybe my user account lacks sufficient privileges.

But since you've added the relation, I won't worry about it.

Thanks.

Noel Duffy
to Bart
Bart wrote 8 lines
On Wed, May 13, 2020 at 10:40 AM Noel Duffy via fpc-pascal > As I've already learned the hard way, the sockets unit is compiled in > "fpc" mode, so there's no "out" parameters. Otherwise I would definitely > have used one. {$modeswicth out} perhaps?

I didn't know this existed. I'm not sure of the implications of its use, though, so I would like to get the opinion of more experienced FPC developers before I use it.

Marco van de Voort
to Noel Duffy: Good idea, and normally I would, but the current implementation of StrToHostAddr (see…

Op 12/05/2020 om 23:05 schreef Noel Duffy via fpc-pascal:

Show quoted text 16 lines
>> function TryStrToHostAddr(IP: String; var ip4: in_addr): Boolean; >> function TryStrToHostAddr6(IP: String; var ip6: in6_addr): Boolean; >> >> Rationale for this request: All conversion calls in sysutils and >> dateutils use this naming scheme, it's good for consistency. >> >> (and I hate underscores, but that's beside the point ;)) >> > Yes to the principle and yes to the TryStrTo naming. But I would make > the IP param CONST ;-) Good idea, and normally I would, but the current implementation of StrToHostAddr (see below) does Delete on IP as it processes it. As it currently stands this function must accept a non-const.

Miight have been when posex() was in strutils, however nowadays Pos() accepts a start index too. Even shortstring only versions.

Michael Van Canneyt
to Noel Duffy: I didn't know this existed. I'm not sure of the implications of its use, though, so I…
Noel Duffy wrote 13 lines
On 13/05/20 9:24 pm, Bart via fpc-pascal wrote: > On Wed, May 13, 2020 at 10:40 AM Noel Duffy via fpc-pascal >> As I've already learned the hard way, the sockets unit is compiled in >> "fpc" mode, so there's no "out" parameters. Otherwise I would definitely >> have used one. > > {$modeswicth out} perhaps? > I didn't know this existed. I'm not sure of the implications of its use, though, so I would like to get the opinion of more experienced FPC developers before I use it.

It's OK to use this.
It just enables the use of the out keyword for the current unit, nothing more. It's safest to add it before the 'interface' keyword.

Michael.

Noel Duffy
to Michael Van Canneyt
Michael Van Canneyt wrote 22 lines
On Wed, 13 May 2020, Noel Duffy via fpc-pascal wrote: > On 13/05/20 9:24 pm, Bart via fpc-pascal wrote: >> On Wed, May 13, 2020 at 10:40 AM Noel Duffy via fpc-pascal > >>> As I've already learned the hard way, the sockets unit is compiled in >>> "fpc" mode, so there's no "out" parameters. Otherwise I would >>> definitely >>> have used one. >> >> {$modeswicth out} perhaps? >> > > I didn't know this existed. I'm not sure of the implications of its > use, though, so I would like to get the opinion of more experienced > FPC developers before I use it. It's OK to use this. It just enables the use of the out keyword for the current unit, nothing more. It's safest to add it before the 'interface' keyword.

OK, I've made a note on the bug report to use {$modeswitch out} and to use out parameters for the function definitions.