I try to create a socket and connect to a remote host. I resolve the remote host from domain with GetAddrInfo. Which works fine. After the call i get a working addrinfo struct with the right values. But in some situations the struct gets corrupted before calling connect().
struct addrinfoW sa = { 0 };
ZeroMemory(&sa, sizeof(sa));
lookup_host(host, &sa);
int sock = 0;
sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock == -1) {
return -1;
}
HeapValidate(GetProcessHeap(), HEAP_NO_SERIALIZE, NULL);
if(connect(sock, sa->ai_addr, sa->ai_addrlen) < 0) {
HeapValidate(GetProcessHeap(), HEAP_NO_SERIALIZE, NULL);
#ifdef _DEBUG
printf("Error: %d\n", GetLastError());
#endif // _DEBUG
return -2;
}
Where lookup_host is defined as:
struct addrinfoW hints = { 0 };
struct addrinfoW *res;
int errcode;
ZeroMemory(&hints, sizeof(struct addrinfoW));
//ZeroMemory(res, sizeof(struct addrinfo));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags |= AI_CANONNAME;
errcode = GetAddrInfo(host, L"80", &hints, &res);//GetAddrInfoExW(L"google.de", L"80", NS_ALL, NULL, &hints, &res, NULL, NULL, NULL, NULL); //GetAddrInfoEX(L"google.de", L"80", &hints, &res);
win_free(mbHost);
if (errcode != 0)
{
//perror("getaddrinfo");
return -1;
}
void *ptr = 0;
while (res)
{
switch (res->ai_family)
{
case AF_INET:
ptr = &((struct sockaddr_in *) res->ai_addr)->sin_addr;
break;
case AF_INET6:
ptr = &((struct sockaddr_in6 *) res->ai_addr)->sin6_addr;
break;
}
CopyMemory(out, res, sizeof(struct addrinfoW));
break;
res = res->ai_next;
}
FreeAddrInfo(res);
So this works well on my Quad-Core Win10 laptop. But if i add for example a
MessageBoxA(NULL, "After sock", "HTTP", MB_ICONWARNING|MB_CANCELTRYCONTINUE | MB_DEFBUTTON2);
call before the connect() call and examine the addrinfo struct in debugger it gets corrupted. For example some time i can see that the ai_canonname which should be "google.com" get overwritten with "After Sock". But the heap is still valid after that. So i have no idea where to start debugging this. Could it be some other buffer or struct which overflows somewhere?
It's because you free all the memory associated with the results before you use it. For example
ai_canonname
is a pointer to a string that is allocated from the heap. The memory containing its bytes is flagged as free for reuse before you exitlookup_host
. YourCopyMemory
will copy the pointer but not the bytes it points to.NB you should post the whole of
lookup_host
including the function definition.You need to find a way of avoiding the call to
FreeAddrInfo
until after you are done. Either that or do a deeper copy of thestruct
including all the things being pointed to which you will find rapidly turns into a rabbit hole.The way I would do it is to provide a callback function that is called while inside
lookup_host