Erreur de segmentation dans getaddrinfo ()
-
26-10-2019 - |
Question
Je me fais erreur de segmentation dans getaddrinfo ().
Ceci est la trace de la pile.
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xb7ff4b70 (LWP 26872)]
__res_vinit (statp=0xb7ff4df4, preinit=0) at res_init.c:176
176 res_init.c: No such file or directory.
in res_init.c
(gdb) bt
#0 __res_vinit (statp=0xb7ff4df4, preinit=0) at res_init.c:176
#1 0x0042fe95 in *__GI___res_ninit (statp=0xb7ff4df4) at res_init.c:142
#2 0x00430ea0 in *__GI___res_maybe_init (resp=0xb7ff4df4, preinit=0) at res_libc.c:122
#3 0x003f86f4 in gaih_inet (name=<value optimized out>, service=<value optimized out>, req=0xb7ff3df8, pai=0xb7ff3db4, naddrs=0xb7ff3da4)
at ../sysdeps/posix/getaddrinfo.c:690
#4 0x003faa65 in *__GI_getaddrinfo (name=0x8203a68 "api.shoutcast.com", service=0x810ae72 "http", hints=0xb7ff3df8, pai=0xb7ff3e24)
at ../sysdeps/posix/getaddrinfo.c:2160
#5 0x08050a87 in test_addrinfo () at /kkkk/myaddrinfo.c:33
La source de la fonction test_addrinfo ();
#ifndef NI_MAXHOST
#define NI_MAXHOST 1025
#endif
struct addrinfo hints =
{
.ai_flags = 0, /* Input flags. nothing special */
.ai_family = PF_UNSPEC,/* Protocol family for socket. any */
.ai_socktype = SOCK_STREAM, /* Socket type. take any (SOCK_RAW, SOCK_STREAM, SOCK_DGRAM) */
.ai_protocol = IPPROTO_TCP, /* Protocol for socket. take any (IPPROTO_TCP and IPPROTO_UDP) */
.ai_addrlen = 0, /* Length of socket address. always 0 */
.ai_addr = NULL, /* Socket address for socket. always NULL */
.ai_canonname = NULL, /* Canonical name for service. always NULL */
.ai_next = NULL, /* Pointer to next in list. always NULL */
};
int test_addrinfo(void)
{
struct addrinfo *result = NULL;
struct addrinfo *res;
int error;
/* resolve the domain name into a list of addresses */
error = getaddrinfo("api.shoutcast.com", "http", &hints, &result);
if (error != 0)
{
fprintf(stderr, "error in getaddrinfo: %s\n", gai_strerror(error));
return EXIT_FAILURE;
}
/* loop over all returned results and do inverse lookup */
for (res = result; res != NULL; res = res->ai_next)
{
char hostname[NI_MAXHOST] = "";
error = getnameinfo(res->ai_addr, res->ai_addrlen, hostname, NI_MAXHOST, NULL, 0, 0);
if (error != 0)
{
fprintf(stderr, "error in getnameinfo: %s\n", gai_strerror(error));
continue;
}
if (*hostname != '\0')
printf("hostname: %s\n", hostname);
}
freeaddrinfo(result);
return EXIT_SUCCESS;
}
Après l'exécution en valgrind, je me suis le journal suivant
==00:00:00:07.590 7788==
==00:00:00:07.590 7788== Process terminating with default action of signal 11 (SIGSEGV)
==00:00:00:07.590 7788== Bad permissions for mapped region at address 0x4033BDC
==00:00:00:07.590 7788== at 0x4348C8A: __res_vinit (res_init.c:176)
==00:00:00:07.645 7788==
Cette test_addrinfo () de fonction est appelée par une couche supérieure dans mon application. Je l'ai testé la même fonction dans une autre application qui a une seule main (). Il a travaillé dans cette application.
Je soupçonnais que je ne suis pas en utilisant la bibliothèque gnulib correcte ou faux drapeaux de compilation. Des indices ou des conseils?
La solution
Je trouve le problème. Il y avait débordement pile comme la fonction getaddrinfo () utilise alloca () - qui alloue dynamiquement de la mémoire, mais sur la pile (et non sur le tas). Cette fonction est très dangereux.
J'ai essayé de mettre le -fstack-protector-all drapeau gcc mais ce fut en vain.