C addrinfo struct gets corrupted. But heap is still valid
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: %dn", 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?
c winsock memory-corruption
add a comment |
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: %dn", 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?
c winsock memory-corruption
add a comment |
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: %dn", 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?
c winsock memory-corruption
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: %dn", 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?
c winsock memory-corruption
c winsock memory-corruption
asked Nov 14 '18 at 12:48
mannermanner
183
183
add a comment |
add a comment |
3 Answers
3
active
oldest
votes
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 exit lookup_host
. Your CopyMemory
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 the struct
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
add a comment |
your while (res) is moving the pointer res
to other nodes other the origibal one each time you execute line res = res->ai_next;
, but then you call FreeAddrInfo(res);
at the end with modified pointer, not the one allocated via GetAddrInfo.
Also, although you don't provide the start of the lookup_host function, but assuming an inout is ptr, you are setting it to the address of sin_addr from the allocated emory, and then freeing the memory at the end of the function, so it may be used by something else.
add a comment |
Your lookup_host()
is not returning address data back to the caller correctly, not even close. addrinfo
contains pointers to data outside of the addrinfo
. But you are just copying the addrinfo
itself to the caller, but none of the data it points at.
Try something more like this instead:
int lookup_host(const wchar_t *host, int family, void *sa)
{
struct addrinfoW hints;
struct addrinfoW *res, *addr;
int errcode, addrlen, returnval;
void *ptr;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = family;
hints.ai_socktype = SOCK_STREAM;
errcode = GetAddrInfoW(host, L"80", &hints, &res);
//GetAddrInfoExW(host, L"80", NS_ALL, NULL, &hints, &res, NULL, NULL, NULL, NULL);
if (errcode != 0)
{
//perror("getaddrinfo");
return -1;
}
returnval = 0;
for(addr = res; addr != NULL; addr = addr->ai_next)
{
switch (addr->ai_family)
{
case AF_INET:
ptr = &((struct sockaddr_in *) addr->ai_addr)->sin_addr;
addrlen = sizeof(struct sockaddr_in);
break;
case AF_INET6:
ptr = &((struct sockaddr_in6 *) res->ai_addr)->sin6_addr;
addrlen = sizeof(struct sockaddr_in6);
break;
default:
continue;
}
CopyMemory(sa, ptr, addrlen);
returnval = 1;
break;
}
FreeAddrInfoW(res);
return returnval;
}
...
struct sockaddr_in sa;
if (lookup_host(host, AF_INET, &sa) != 1) {
return -1;
}
SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET) {
return -1;
}
if (connect(sock, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
#ifdef _DEBUG
printf("Error: %dn", GetLastError());
#endif // _DEBUG
closesocket(sock);
return -2;
}
...
Note, however, that the above returns only the first address found. A hostname can resolve to multiple IPs, and your PC might not have a route to all of them. So, you should attempt to connect to every address reported until one is successful, eg:
int lookup_host(const wchar_t *host, int family, struct addrinfoW **addrs)
{
struct addrinfoW hints;
int errcode;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = family;
hints.ai_socktype = SOCK_STREAM;
errcode = GetAddrInfoW(host, L"80", &hints, addrs);
//GetAddrInfoExW(host, L"80", NS_ALL, NULL, &hints, addrs, NULL, NULL, NULL, NULL);
if (errcode != 0)
{
//perror("getaddrinfo");
return -1;
}
return 0;
}
...
struct addrInfoW *res, *addr;
if (lookup_host(host, AF_INET, &res) < 0) { // or AF_INET6, or AF_UNSPEC
return -1;
}
sock = INVALID_SOCKET;
for(addr = res; addr != NULL; addr = addr->ai_next)
{
sock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
if (sock == INVALID_SOCKET) {
break;
}
if (connect(sock, addr->ai_addr, addr->ai_addrlen) == 0) {
break;
}
#ifdef _DEBUG
printf("Error: %dn", GetLastError());
#endif // _DEBUG
closesocket(sock);
sock = INVALID_SOCKET;
}
FreeAddrInfoW(res);
if (sock == INVALID_SOCKET) {
return -2;
}
...
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53300622%2fc-addrinfo-struct-gets-corrupted-but-heap-is-still-valid%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
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 exit lookup_host
. Your CopyMemory
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 the struct
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
add a comment |
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 exit lookup_host
. Your CopyMemory
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 the struct
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
add a comment |
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 exit lookup_host
. Your CopyMemory
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 the struct
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
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 exit lookup_host
. Your CopyMemory
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 the struct
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
answered Nov 14 '18 at 13:07
JeremyPJeremyP
74.4k13107145
74.4k13107145
add a comment |
add a comment |
your while (res) is moving the pointer res
to other nodes other the origibal one each time you execute line res = res->ai_next;
, but then you call FreeAddrInfo(res);
at the end with modified pointer, not the one allocated via GetAddrInfo.
Also, although you don't provide the start of the lookup_host function, but assuming an inout is ptr, you are setting it to the address of sin_addr from the allocated emory, and then freeing the memory at the end of the function, so it may be used by something else.
add a comment |
your while (res) is moving the pointer res
to other nodes other the origibal one each time you execute line res = res->ai_next;
, but then you call FreeAddrInfo(res);
at the end with modified pointer, not the one allocated via GetAddrInfo.
Also, although you don't provide the start of the lookup_host function, but assuming an inout is ptr, you are setting it to the address of sin_addr from the allocated emory, and then freeing the memory at the end of the function, so it may be used by something else.
add a comment |
your while (res) is moving the pointer res
to other nodes other the origibal one each time you execute line res = res->ai_next;
, but then you call FreeAddrInfo(res);
at the end with modified pointer, not the one allocated via GetAddrInfo.
Also, although you don't provide the start of the lookup_host function, but assuming an inout is ptr, you are setting it to the address of sin_addr from the allocated emory, and then freeing the memory at the end of the function, so it may be used by something else.
your while (res) is moving the pointer res
to other nodes other the origibal one each time you execute line res = res->ai_next;
, but then you call FreeAddrInfo(res);
at the end with modified pointer, not the one allocated via GetAddrInfo.
Also, although you don't provide the start of the lookup_host function, but assuming an inout is ptr, you are setting it to the address of sin_addr from the allocated emory, and then freeing the memory at the end of the function, so it may be used by something else.
answered Nov 14 '18 at 13:06
lostbardlostbard
3,1031311
3,1031311
add a comment |
add a comment |
Your lookup_host()
is not returning address data back to the caller correctly, not even close. addrinfo
contains pointers to data outside of the addrinfo
. But you are just copying the addrinfo
itself to the caller, but none of the data it points at.
Try something more like this instead:
int lookup_host(const wchar_t *host, int family, void *sa)
{
struct addrinfoW hints;
struct addrinfoW *res, *addr;
int errcode, addrlen, returnval;
void *ptr;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = family;
hints.ai_socktype = SOCK_STREAM;
errcode = GetAddrInfoW(host, L"80", &hints, &res);
//GetAddrInfoExW(host, L"80", NS_ALL, NULL, &hints, &res, NULL, NULL, NULL, NULL);
if (errcode != 0)
{
//perror("getaddrinfo");
return -1;
}
returnval = 0;
for(addr = res; addr != NULL; addr = addr->ai_next)
{
switch (addr->ai_family)
{
case AF_INET:
ptr = &((struct sockaddr_in *) addr->ai_addr)->sin_addr;
addrlen = sizeof(struct sockaddr_in);
break;
case AF_INET6:
ptr = &((struct sockaddr_in6 *) res->ai_addr)->sin6_addr;
addrlen = sizeof(struct sockaddr_in6);
break;
default:
continue;
}
CopyMemory(sa, ptr, addrlen);
returnval = 1;
break;
}
FreeAddrInfoW(res);
return returnval;
}
...
struct sockaddr_in sa;
if (lookup_host(host, AF_INET, &sa) != 1) {
return -1;
}
SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET) {
return -1;
}
if (connect(sock, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
#ifdef _DEBUG
printf("Error: %dn", GetLastError());
#endif // _DEBUG
closesocket(sock);
return -2;
}
...
Note, however, that the above returns only the first address found. A hostname can resolve to multiple IPs, and your PC might not have a route to all of them. So, you should attempt to connect to every address reported until one is successful, eg:
int lookup_host(const wchar_t *host, int family, struct addrinfoW **addrs)
{
struct addrinfoW hints;
int errcode;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = family;
hints.ai_socktype = SOCK_STREAM;
errcode = GetAddrInfoW(host, L"80", &hints, addrs);
//GetAddrInfoExW(host, L"80", NS_ALL, NULL, &hints, addrs, NULL, NULL, NULL, NULL);
if (errcode != 0)
{
//perror("getaddrinfo");
return -1;
}
return 0;
}
...
struct addrInfoW *res, *addr;
if (lookup_host(host, AF_INET, &res) < 0) { // or AF_INET6, or AF_UNSPEC
return -1;
}
sock = INVALID_SOCKET;
for(addr = res; addr != NULL; addr = addr->ai_next)
{
sock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
if (sock == INVALID_SOCKET) {
break;
}
if (connect(sock, addr->ai_addr, addr->ai_addrlen) == 0) {
break;
}
#ifdef _DEBUG
printf("Error: %dn", GetLastError());
#endif // _DEBUG
closesocket(sock);
sock = INVALID_SOCKET;
}
FreeAddrInfoW(res);
if (sock == INVALID_SOCKET) {
return -2;
}
...
add a comment |
Your lookup_host()
is not returning address data back to the caller correctly, not even close. addrinfo
contains pointers to data outside of the addrinfo
. But you are just copying the addrinfo
itself to the caller, but none of the data it points at.
Try something more like this instead:
int lookup_host(const wchar_t *host, int family, void *sa)
{
struct addrinfoW hints;
struct addrinfoW *res, *addr;
int errcode, addrlen, returnval;
void *ptr;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = family;
hints.ai_socktype = SOCK_STREAM;
errcode = GetAddrInfoW(host, L"80", &hints, &res);
//GetAddrInfoExW(host, L"80", NS_ALL, NULL, &hints, &res, NULL, NULL, NULL, NULL);
if (errcode != 0)
{
//perror("getaddrinfo");
return -1;
}
returnval = 0;
for(addr = res; addr != NULL; addr = addr->ai_next)
{
switch (addr->ai_family)
{
case AF_INET:
ptr = &((struct sockaddr_in *) addr->ai_addr)->sin_addr;
addrlen = sizeof(struct sockaddr_in);
break;
case AF_INET6:
ptr = &((struct sockaddr_in6 *) res->ai_addr)->sin6_addr;
addrlen = sizeof(struct sockaddr_in6);
break;
default:
continue;
}
CopyMemory(sa, ptr, addrlen);
returnval = 1;
break;
}
FreeAddrInfoW(res);
return returnval;
}
...
struct sockaddr_in sa;
if (lookup_host(host, AF_INET, &sa) != 1) {
return -1;
}
SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET) {
return -1;
}
if (connect(sock, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
#ifdef _DEBUG
printf("Error: %dn", GetLastError());
#endif // _DEBUG
closesocket(sock);
return -2;
}
...
Note, however, that the above returns only the first address found. A hostname can resolve to multiple IPs, and your PC might not have a route to all of them. So, you should attempt to connect to every address reported until one is successful, eg:
int lookup_host(const wchar_t *host, int family, struct addrinfoW **addrs)
{
struct addrinfoW hints;
int errcode;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = family;
hints.ai_socktype = SOCK_STREAM;
errcode = GetAddrInfoW(host, L"80", &hints, addrs);
//GetAddrInfoExW(host, L"80", NS_ALL, NULL, &hints, addrs, NULL, NULL, NULL, NULL);
if (errcode != 0)
{
//perror("getaddrinfo");
return -1;
}
return 0;
}
...
struct addrInfoW *res, *addr;
if (lookup_host(host, AF_INET, &res) < 0) { // or AF_INET6, or AF_UNSPEC
return -1;
}
sock = INVALID_SOCKET;
for(addr = res; addr != NULL; addr = addr->ai_next)
{
sock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
if (sock == INVALID_SOCKET) {
break;
}
if (connect(sock, addr->ai_addr, addr->ai_addrlen) == 0) {
break;
}
#ifdef _DEBUG
printf("Error: %dn", GetLastError());
#endif // _DEBUG
closesocket(sock);
sock = INVALID_SOCKET;
}
FreeAddrInfoW(res);
if (sock == INVALID_SOCKET) {
return -2;
}
...
add a comment |
Your lookup_host()
is not returning address data back to the caller correctly, not even close. addrinfo
contains pointers to data outside of the addrinfo
. But you are just copying the addrinfo
itself to the caller, but none of the data it points at.
Try something more like this instead:
int lookup_host(const wchar_t *host, int family, void *sa)
{
struct addrinfoW hints;
struct addrinfoW *res, *addr;
int errcode, addrlen, returnval;
void *ptr;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = family;
hints.ai_socktype = SOCK_STREAM;
errcode = GetAddrInfoW(host, L"80", &hints, &res);
//GetAddrInfoExW(host, L"80", NS_ALL, NULL, &hints, &res, NULL, NULL, NULL, NULL);
if (errcode != 0)
{
//perror("getaddrinfo");
return -1;
}
returnval = 0;
for(addr = res; addr != NULL; addr = addr->ai_next)
{
switch (addr->ai_family)
{
case AF_INET:
ptr = &((struct sockaddr_in *) addr->ai_addr)->sin_addr;
addrlen = sizeof(struct sockaddr_in);
break;
case AF_INET6:
ptr = &((struct sockaddr_in6 *) res->ai_addr)->sin6_addr;
addrlen = sizeof(struct sockaddr_in6);
break;
default:
continue;
}
CopyMemory(sa, ptr, addrlen);
returnval = 1;
break;
}
FreeAddrInfoW(res);
return returnval;
}
...
struct sockaddr_in sa;
if (lookup_host(host, AF_INET, &sa) != 1) {
return -1;
}
SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET) {
return -1;
}
if (connect(sock, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
#ifdef _DEBUG
printf("Error: %dn", GetLastError());
#endif // _DEBUG
closesocket(sock);
return -2;
}
...
Note, however, that the above returns only the first address found. A hostname can resolve to multiple IPs, and your PC might not have a route to all of them. So, you should attempt to connect to every address reported until one is successful, eg:
int lookup_host(const wchar_t *host, int family, struct addrinfoW **addrs)
{
struct addrinfoW hints;
int errcode;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = family;
hints.ai_socktype = SOCK_STREAM;
errcode = GetAddrInfoW(host, L"80", &hints, addrs);
//GetAddrInfoExW(host, L"80", NS_ALL, NULL, &hints, addrs, NULL, NULL, NULL, NULL);
if (errcode != 0)
{
//perror("getaddrinfo");
return -1;
}
return 0;
}
...
struct addrInfoW *res, *addr;
if (lookup_host(host, AF_INET, &res) < 0) { // or AF_INET6, or AF_UNSPEC
return -1;
}
sock = INVALID_SOCKET;
for(addr = res; addr != NULL; addr = addr->ai_next)
{
sock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
if (sock == INVALID_SOCKET) {
break;
}
if (connect(sock, addr->ai_addr, addr->ai_addrlen) == 0) {
break;
}
#ifdef _DEBUG
printf("Error: %dn", GetLastError());
#endif // _DEBUG
closesocket(sock);
sock = INVALID_SOCKET;
}
FreeAddrInfoW(res);
if (sock == INVALID_SOCKET) {
return -2;
}
...
Your lookup_host()
is not returning address data back to the caller correctly, not even close. addrinfo
contains pointers to data outside of the addrinfo
. But you are just copying the addrinfo
itself to the caller, but none of the data it points at.
Try something more like this instead:
int lookup_host(const wchar_t *host, int family, void *sa)
{
struct addrinfoW hints;
struct addrinfoW *res, *addr;
int errcode, addrlen, returnval;
void *ptr;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = family;
hints.ai_socktype = SOCK_STREAM;
errcode = GetAddrInfoW(host, L"80", &hints, &res);
//GetAddrInfoExW(host, L"80", NS_ALL, NULL, &hints, &res, NULL, NULL, NULL, NULL);
if (errcode != 0)
{
//perror("getaddrinfo");
return -1;
}
returnval = 0;
for(addr = res; addr != NULL; addr = addr->ai_next)
{
switch (addr->ai_family)
{
case AF_INET:
ptr = &((struct sockaddr_in *) addr->ai_addr)->sin_addr;
addrlen = sizeof(struct sockaddr_in);
break;
case AF_INET6:
ptr = &((struct sockaddr_in6 *) res->ai_addr)->sin6_addr;
addrlen = sizeof(struct sockaddr_in6);
break;
default:
continue;
}
CopyMemory(sa, ptr, addrlen);
returnval = 1;
break;
}
FreeAddrInfoW(res);
return returnval;
}
...
struct sockaddr_in sa;
if (lookup_host(host, AF_INET, &sa) != 1) {
return -1;
}
SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET) {
return -1;
}
if (connect(sock, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
#ifdef _DEBUG
printf("Error: %dn", GetLastError());
#endif // _DEBUG
closesocket(sock);
return -2;
}
...
Note, however, that the above returns only the first address found. A hostname can resolve to multiple IPs, and your PC might not have a route to all of them. So, you should attempt to connect to every address reported until one is successful, eg:
int lookup_host(const wchar_t *host, int family, struct addrinfoW **addrs)
{
struct addrinfoW hints;
int errcode;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = family;
hints.ai_socktype = SOCK_STREAM;
errcode = GetAddrInfoW(host, L"80", &hints, addrs);
//GetAddrInfoExW(host, L"80", NS_ALL, NULL, &hints, addrs, NULL, NULL, NULL, NULL);
if (errcode != 0)
{
//perror("getaddrinfo");
return -1;
}
return 0;
}
...
struct addrInfoW *res, *addr;
if (lookup_host(host, AF_INET, &res) < 0) { // or AF_INET6, or AF_UNSPEC
return -1;
}
sock = INVALID_SOCKET;
for(addr = res; addr != NULL; addr = addr->ai_next)
{
sock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
if (sock == INVALID_SOCKET) {
break;
}
if (connect(sock, addr->ai_addr, addr->ai_addrlen) == 0) {
break;
}
#ifdef _DEBUG
printf("Error: %dn", GetLastError());
#endif // _DEBUG
closesocket(sock);
sock = INVALID_SOCKET;
}
FreeAddrInfoW(res);
if (sock == INVALID_SOCKET) {
return -2;
}
...
edited Nov 14 '18 at 21:52
answered Nov 14 '18 at 21:40
Remy LebeauRemy Lebeau
336k18256451
336k18256451
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53300622%2fc-addrinfo-struct-gets-corrupted-but-heap-is-still-valid%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown