[ 
https://issues.apache.org/jira/browse/ZOOKEEPER-208?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Patrick Hunt updated ZOOKEEPER-208:
-----------------------------------

    Description: 
The Zookeeper C client library uses gethostbyname and strtok, both of which are 
not safe to use from multiple threads.

The problem is resolved by using getaddrinfo and strtok_r in place of the older 
API.



  was:
The Zookeeper C client library uses gethostbyname and strtok, both of which are 
not safe to use from multiple threads. Below is the original patch we made 
which fixes the problem.

The problem is resolved by using getaddrinfo and strtok_r in place of the older 
API.

Patch for zookeeper-c-client-2.2.1/src/zookeeper.c (2008-06-09 on SF.net)

241c241
<     struct hostent *he;
---
>       struct addrinfo hints, *res, *res0;
243,245d242
<     struct sockaddr_in *addr4;
<     struct sockaddr_in6 *addr6;
<     char **ptr;
247a245
>       char *strtok_last;
263c261
<     host=strtok(hosts, ",");
---
>     host=strtok_r(hosts, ",", &strtok_last);
283,294c281,297
<         he = gethostbyname(host);
<         if (!he) {
<             LOG_ERROR(("could not resolve %s", host));
<             errno=EINVAL;
<             rc=ZBADARGUMENTS;
<             goto fail;
<         }
<
<         /* Setup the address array */
<         for(ptr = he->h_addr_list;*ptr != 0; ptr++) {
<             if (zh->addrs_count == alen) {
<                 void *tmpaddr;
---
>               
>               memset(&hints, 0, sizeof(hints));
>               hints.ai_flags = AI_ADDRCONFIG;
>               hints.ai_family = AF_UNSPEC;
>               hints.ai_socktype = SOCK_STREAM;
>               hints.ai_protocol = IPPROTO_TCP;
>
>               if (getaddrinfo(host, port_spec, &hints, &res0) != 0) {
>                       LOG_ERROR(("getaddrinfo: %s\n", strerror(errno)));
>                       rc=ZSYSTEMERROR;
>                       goto fail;
>               }
>               
>               for (res = res0; res; res = res->ai_next) {
>                       // Expand address list if needed
>                       if (zh->addrs_count == alen) {
>                               void *tmpaddr;
304,313c307,312
<             }
<             addr = &zh->addrs[zh->addrs_count];
<             addr4 = (struct sockaddr_in*)addr;
<             addr6 = (struct sockaddr_in6*)addr;
<             addr->sa_family = he->h_addrtype;
<             if (addr->sa_family == AF_INET) {
<                 addr4->sin_port = htons(port);
<                 memset(&addr4->sin_zero, 0, sizeof(addr4->sin_zero));
<                 memcpy(&addr4->sin_addr, *ptr, he->h_length);
<                 zh->addrs_count++;
---
>                       }
>                       
>                       // Copy addrinfo into address list
>                       addr = &zh->addrs[zh->addrs_count];
>                       switch (res->ai_family) {
>                       case AF_INET:
315,320c314
<             } else if (addr->sa_family == AF_INET6) {
<                 addr6->sin6_port = htons(port);
<                 addr6->sin6_scope_id = 0;
<                 addr6->sin6_flowinfo = 0;
<                 memcpy(&addr6->sin6_addr, *ptr, he->h_length);
<                 zh->addrs_count++;
---
>                       case AF_INET6:
322,327c316,328
<             } else {
<                 LOG_WARN(("skipping unknown address family %x for %s",
<                         addr->sa_family, zh->hostname));
<             }
<         }
<         host = strtok(0, ",");
---
>                               memcpy(addr, res->ai_addr, res->ai_addrlen);
>                               ++zh->addrs_count;
>                               break;
>                       default:
>                               LOG_WARN(("skipping unknown address family %x 
> for %s",
>                                       res->ai_family, zh->hostname));
>                               break;
>                       }
>               }
>               
>               freeaddrinfo(res0);
>
>               host = strtok_r(0, ",", &strtok_last);
329a331
>



I've updated the summary now that the changes are attached. If the original 
author doesn't approve then perhaps we can get someone who's untainted to 
create a new patch.


> Zookeeper C client uses API that are not thread safe, causing crashes when 
> multiple instances are active
> --------------------------------------------------------------------------------------------------------
>
>                 Key: ZOOKEEPER-208
>                 URL: https://issues.apache.org/jira/browse/ZOOKEEPER-208
>             Project: Zookeeper
>          Issue Type: Bug
>          Components: c client
>    Affects Versions: 3.0.0
>         Environment: Linux
>            Reporter: Austin Shoemaker
>            Assignee: Austin Shoemaker
>            Priority: Critical
>             Fix For: 3.1.0
>
>         Attachments: zookeeper-strtok_getaddrinfo-trunk.patch
>
>
> The Zookeeper C client library uses gethostbyname and strtok, both of which 
> are not safe to use from multiple threads.
> The problem is resolved by using getaddrinfo and strtok_r in place of the 
> older API.

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.

Reply via email to