From: Donat Enikeev Subject: [PATCH 1/2] dnsapi: migrating to res_nquery (ver.3) Message-Id: <1452846935-16312-1-git-send-email-donat@enikeev.net> Date: Fri, 15 Jan 2016 11:35:34 +0300 1. Style, extra checks and potential memory leackage fix (per Hans Leidekker feedback in substance) 2. Using debugstr_a() when tracing untrusted values of arbitrary size (per Sebastian Lackner) Signed-off-by: Donat Enikeev --- dlls/dnsapi/query.c | 72 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 49 insertions(+), 23 deletions(-) diff --git a/dlls/dnsapi/query.c b/dlls/dnsapi/query.c index a66db37..7fafb48 100644 --- a/dlls/dnsapi/query.c +++ b/dlls/dnsapi/query.c @@ -46,6 +46,10 @@ #include "winnls.h" #include "windns.h" #include "nb30.h" +#define USE_WS_PREFIX +#include "inaddr.h" +#include "in6addr.h" +#include "ws2tcpip.h" #include "dnsapi.h" @@ -53,12 +57,19 @@ WINE_DEFAULT_DEBUG_CHANNEL(dnsapi); #ifdef HAVE_RESOLV -/* call res_init() just once because of a bug in Mac OS X 10.4 */ -/* call once per thread on systems that have per-thread _res */ -static void initialise_resolver( void ) +static res_state initialise_resolver( void ) { - if ((_res.options & RES_INIT) == 0) - res_init(); + res_state rs; + if ( !(rs = heap_alloc_zero(sizeof(struct __res_state))) ) + return NULL; + + if ( res_ninit(rs) == -1 ) + { + heap_free(rs); + return NULL; + } + + return rs; } static const char *dns_section_to_str( ns_sect section ) @@ -543,7 +554,7 @@ exit: /* res_init() must have been called before calling these three functions. */ -static DNS_STATUS dns_set_serverlist( const IP4_ARRAY *addrs ) +static DNS_STATUS dns_set_serverlist( res_state rs, const IP4_ARRAY *addrs ) { int i; @@ -551,38 +562,39 @@ static DNS_STATUS dns_set_serverlist( const IP4_ARRAY *addrs ) { WARN( "too many servers: %d only using the first: %d\n", addrs->AddrCount, MAXNS ); - _res.nscount = MAXNS; + rs->nscount = MAXNS; } - else _res.nscount = addrs->AddrCount; + else + rs->nscount = addrs->AddrCount; - for (i = 0; i < _res.nscount; i++) - _res.nsaddr_list[i].sin_addr.s_addr = addrs->AddrArray[i]; + for (i = 0; i < rs->nscount; i++) + rs->nsaddr_list[i].sin_addr.s_addr = addrs->AddrArray[i]; return ERROR_SUCCESS; } -static DNS_STATUS dns_get_serverlist( PIP4_ARRAY addrs, PDWORD len ) +static DNS_STATUS dns_get_serverlist( res_state rs, PIP4_ARRAY addrs, PDWORD len ) { unsigned int size; int i; - size = FIELD_OFFSET(IP4_ARRAY, AddrArray[_res.nscount]); + size = FIELD_OFFSET(IP4_ARRAY, AddrArray[rs->nscount]); if (!addrs || *len < size) { *len = size; return ERROR_INSUFFICIENT_BUFFER; } - addrs->AddrCount = _res.nscount; + addrs->AddrCount = rs->nscount; - for (i = 0; i < _res.nscount; i++) - addrs->AddrArray[i] = _res.nsaddr_list[i].sin_addr.s_addr; + for (i = 0; i < rs->nscount; i++) + addrs->AddrArray[i] = rs->nsaddr_list[i].sin_addr.s_addr; return ERROR_SUCCESS; } #define DNS_MAX_PACKET_SIZE 4096 -static DNS_STATUS dns_do_query( PCSTR name, WORD type, DWORD options, PDNS_RECORDA *result ) +static DNS_STATUS dns_do_query( res_state rs, PCSTR name, WORD type, DWORD options, PDNS_RECORDA *result ) { DNS_STATUS ret = DNS_ERROR_RCODE_NOT_IMPLEMENTED; @@ -597,7 +609,9 @@ static DNS_STATUS dns_do_query( PCSTR name, WORD type, DWORD options, PDNS_RECOR DNS_RRSET_INIT( rrset ); - len = res_query( name, ns_c_in, type, answer, sizeof(answer) ); + TRACE("Performing res_nquery(%p, %s, %u, %u, %p)\n", rs, debugstr_a(name), type, options, result); + + len = res_nquery( rs, name, ns_c_in, type, answer, sizeof(answer) ); if (len < 0) { ret = dns_map_h_errno( h_errno ); @@ -706,6 +720,7 @@ DNS_STATUS WINAPI DnsQuery_UTF8( PCSTR name, WORD type, DWORD options, PVOID ser { DNS_STATUS ret = DNS_ERROR_RCODE_NOT_IMPLEMENTED; #ifdef HAVE_RESOLV + res_state rs; TRACE( "(%s,%s,0x%08x,%p,%p,%p)\n", debugstr_a(name), dns_type_to_str( type ), options, servers, result, reserved ); @@ -713,13 +728,18 @@ DNS_STATUS WINAPI DnsQuery_UTF8( PCSTR name, WORD type, DWORD options, PVOID ser if (!name || !result) return ERROR_INVALID_PARAMETER; - initialise_resolver(); - _res.options |= dns_map_options( options ); + rs = initialise_resolver(); + if ( !rs ) return ERROR_NOT_ENOUGH_MEMORY; - if (servers && (ret = dns_set_serverlist( servers ))) + rs->options |= dns_map_options( options ); + + if (servers && (ret = dns_set_serverlist( rs, servers ))) + { + heap_free(rs); return ret; + } - ret = dns_do_query( name, type, options, result ); + ret = dns_do_query( rs, name, type, options, result ); if (ret == DNS_ERROR_RCODE_NAME_ERROR && type == DNS_TYPE_A && !(options & DNS_QUERY_NO_NETBT)) @@ -728,6 +748,8 @@ DNS_STATUS WINAPI DnsQuery_UTF8( PCSTR name, WORD type, DWORD options, PVOID ser ret = dns_do_query_netbios( name, result ); } + heap_free(rs); + #endif return ret; } @@ -824,8 +846,12 @@ DNS_STATUS WINAPI DnsQueryConfig( DNS_CONFIG_TYPE config, DWORD flag, PCWSTR ada case DnsConfigDnsServerList: { #ifdef HAVE_RESOLV - initialise_resolver(); - ret = dns_get_serverlist( buffer, len ); + res_state rs = initialise_resolver(); + if (!rs) return ERROR_NOT_ENOUGH_MEMORY; + + ret = dns_get_serverlist( rs, buffer, len ); + + heap_free(rs); break; #else WARN( "compiled without resolver support\n" ); -- 2.5.0