[2/2] c++tools: Work around a BSD bug in getaddrinfo().

Message ID 20220313231603.12480-1-iain@sandoe.co.uk
State Committed
Commit 41f01c97153d403fb34eefac245bab8ba472beea
Headers
Series [1/2] libcody: Do not use a dummy port number in getaddrinfo(). |

Commit Message

Iain Sandoe March 13, 2022, 11:16 p.m. UTC
  Some versions of the BSD getaddrinfo() call do not work with the specific
input of "0" for the servname entry (a segv results).  Since we are making
the call with a dummy port number, the value is actually not important, other
than it should be in range.  Work around the BSD bug by using "1" instead.

tested on powerpc,i686-darwin9, x86-64-darwin10,17,20 
powerpc64le,powerpc64,x86_64-linux-gnu,

OK for master?
eventual backports?
thanks
Iain

Signed-off-by: Iain Sandoe <iain@sandoe.co.uk>

c++tools/ChangeLog:

	* server.cc (accept_from): Use "1" as the dummy port number.
---
 c++tools/server.cc | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
  

Comments

Richard Biener March 14, 2022, 7:45 a.m. UTC | #1
On Mon, Mar 14, 2022 at 12:17 AM Iain Sandoe via Gcc-patches
<gcc-patches@gcc.gnu.org> wrote:
>
> Some versions of the BSD getaddrinfo() call do not work with the specific
> input of "0" for the servname entry (a segv results).  Since we are making
> the call with a dummy port number, the value is actually not important, other
> than it should be in range.  Work around the BSD bug by using "1" instead.
>
> tested on powerpc,i686-darwin9, x86-64-darwin10,17,20
> powerpc64le,powerpc64,x86_64-linux-gnu,
>
> OK for master?
> eventual backports?

Why does the nullptr solution not work here?

> thanks
> Iain
>
> Signed-off-by: Iain Sandoe <iain@sandoe.co.uk>
>
> c++tools/ChangeLog:
>
>         * server.cc (accept_from): Use "1" as the dummy port number.
> ---
>  c++tools/server.cc | 6 +++++-
>  1 file changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/c++tools/server.cc b/c++tools/server.cc
> index 8c6ad314886..00154a05925 100644
> --- a/c++tools/server.cc
> +++ b/c++tools/server.cc
> @@ -360,7 +360,11 @@ accept_from (char *arg ATTRIBUTE_UNUSED)
>    hints.ai_next = NULL;
>
>    struct addrinfo *addrs = NULL;
> -  if (int e = getaddrinfo (slash == arg ? NULL : arg, "0", &hints, &addrs))
> +  /* getaddrinfo requires either hostname or servname to be non-null, so that we must
> +     set a port number (to cover the case that the string passed contains just /NN).
> +     Use an arbitrary in-range port number, but avoiding "0" which triggers a bug on
> +     some BSD variants.  */
> +  if (int e = getaddrinfo (slash == arg ? NULL : arg, "1", &hints, &addrs))
>      {
>        noisy ("cannot resolve '%s': %s", arg, gai_strerror (e));
>        ok = false;
> --
> 2.24.3 (Apple Git-128)
>
  
Iain Sandoe March 14, 2022, 8:03 a.m. UTC | #2
> On 14 Mar 2022, at 07:45, Richard Biener <richard.guenther@gmail.com> wrote:
> 
> On Mon, Mar 14, 2022 at 12:17 AM Iain Sandoe via Gcc-patches
> <gcc-patches@gcc.gnu.org> wrote:
>> 
>> Some versions of the BSD getaddrinfo() call do not work with the specific
>> input of "0" for the servname entry (a segv results).  Since we are making
>> the call with a dummy port number, the value is actually not important, other
>> than it should be in range.  Work around the BSD bug by using "1" instead.
>> 
>> tested on powerpc,i686-darwin9, x86-64-darwin10,17,20
>> powerpc64le,powerpc64,x86_64-linux-gnu,
>> 
>> OK for master?
>> eventual backports?
> 
> Why does the nullptr solution not work here?

Because this code is setting a netmask and, if I read it correctly (we do not seem to have
a test for it), it can be called with “/NN” (where NN is the number of bits and there is no host
name before the slash).

So in this case, in the getaddrinfo() call, the “hostname” parm is set to NULL, and we must
supply a service-name/port number (for the “servname” parm), since getaddrinfo() does not
permit both to be NULL.


> 
>> thanks
>> Iain
>> 
>> Signed-off-by: Iain Sandoe <iain@sandoe.co.uk>
>> 
>> c++tools/ChangeLog:
>> 
>>        * server.cc (accept_from): Use "1" as the dummy port number.
>> ---
>> c++tools/server.cc | 6 +++++-
>> 1 file changed, 5 insertions(+), 1 deletion(-)
>> 
>> diff --git a/c++tools/server.cc b/c++tools/server.cc
>> index 8c6ad314886..00154a05925 100644
>> --- a/c++tools/server.cc
>> +++ b/c++tools/server.cc
>> @@ -360,7 +360,11 @@ accept_from (char *arg ATTRIBUTE_UNUSED)
>>   hints.ai_next = NULL;
>> 
>>   struct addrinfo *addrs = NULL;
>> -  if (int e = getaddrinfo (slash == arg ? NULL : arg, "0", &hints, &addrs))
>> +  /* getaddrinfo requires either hostname or servname to be non-null, so that we must
>> +     set a port number (to cover the case that the string passed contains just /NN).
>> +     Use an arbitrary in-range port number, but avoiding "0" which triggers a bug on
>> +     some BSD variants.  */
>> +  if (int e = getaddrinfo (slash == arg ? NULL : arg, "1", &hints, &addrs))
>>     {
>>       noisy ("cannot resolve '%s': %s", arg, gai_strerror (e));
>>       ok = false;
>> --
>> 2.24.3 (Apple Git-128)
>>
  
Richard Biener March 14, 2022, 10:35 a.m. UTC | #3
On Mon, Mar 14, 2022 at 9:03 AM Iain Sandoe <iain@sandoe.co.uk> wrote:
>
>
>
> > On 14 Mar 2022, at 07:45, Richard Biener <richard.guenther@gmail.com> wrote:
> >
> > On Mon, Mar 14, 2022 at 12:17 AM Iain Sandoe via Gcc-patches
> > <gcc-patches@gcc.gnu.org> wrote:
> >>
> >> Some versions of the BSD getaddrinfo() call do not work with the specific
> >> input of "0" for the servname entry (a segv results).  Since we are making
> >> the call with a dummy port number, the value is actually not important, other
> >> than it should be in range.  Work around the BSD bug by using "1" instead.
> >>
> >> tested on powerpc,i686-darwin9, x86-64-darwin10,17,20
> >> powerpc64le,powerpc64,x86_64-linux-gnu,
> >>
> >> OK for master?
> >> eventual backports?
> >
> > Why does the nullptr solution not work here?
>
> Because this code is setting a netmask and, if I read it correctly (we do not seem to have
> a test for it), it can be called with “/NN” (where NN is the number of bits and there is no host
> name before the slash).
>
> So in this case, in the getaddrinfo() call, the “hostname” parm is set to NULL, and we must
> supply a service-name/port number (for the “servname” parm), since getaddrinfo() does not
> permit both to be NULL.

I see.  I guess the fix is OK then.

Richard.

>
> >
> >> thanks
> >> Iain
> >>
> >> Signed-off-by: Iain Sandoe <iain@sandoe.co.uk>
> >>
> >> c++tools/ChangeLog:
> >>
> >>        * server.cc (accept_from): Use "1" as the dummy port number.
> >> ---
> >> c++tools/server.cc | 6 +++++-
> >> 1 file changed, 5 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/c++tools/server.cc b/c++tools/server.cc
> >> index 8c6ad314886..00154a05925 100644
> >> --- a/c++tools/server.cc
> >> +++ b/c++tools/server.cc
> >> @@ -360,7 +360,11 @@ accept_from (char *arg ATTRIBUTE_UNUSED)
> >>   hints.ai_next = NULL;
> >>
> >>   struct addrinfo *addrs = NULL;
> >> -  if (int e = getaddrinfo (slash == arg ? NULL : arg, "0", &hints, &addrs))
> >> +  /* getaddrinfo requires either hostname or servname to be non-null, so that we must
> >> +     set a port number (to cover the case that the string passed contains just /NN).
> >> +     Use an arbitrary in-range port number, but avoiding "0" which triggers a bug on
> >> +     some BSD variants.  */
> >> +  if (int e = getaddrinfo (slash == arg ? NULL : arg, "1", &hints, &addrs))
> >>     {
> >>       noisy ("cannot resolve '%s': %s", arg, gai_strerror (e));
> >>       ok = false;
> >> --
> >> 2.24.3 (Apple Git-128)
> >>
>
  

Patch

diff --git a/c++tools/server.cc b/c++tools/server.cc
index 8c6ad314886..00154a05925 100644
--- a/c++tools/server.cc
+++ b/c++tools/server.cc
@@ -360,7 +360,11 @@  accept_from (char *arg ATTRIBUTE_UNUSED)
   hints.ai_next = NULL;
 
   struct addrinfo *addrs = NULL;
-  if (int e = getaddrinfo (slash == arg ? NULL : arg, "0", &hints, &addrs))
+  /* getaddrinfo requires either hostname or servname to be non-null, so that we must
+     set a port number (to cover the case that the string passed contains just /NN).
+     Use an arbitrary in-range port number, but avoiding "0" which triggers a bug on
+     some BSD variants.  */
+  if (int e = getaddrinfo (slash == arg ? NULL : arg, "1", &hints, &addrs))
     {
       noisy ("cannot resolve '%s': %s", arg, gai_strerror (e));
       ok = false;