/* $Id$ */ /*** This file is part of avahi. avahi is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. avahi is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with avahi; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ /* Regression test for Avahi bug #84. * This program tests whether the avahi_dns_packet_consume_name function * returns (rather than spinning forever). For a function as simple as * avahi_dns_packet_consume_name, we assume that 1 second of CPU time ≈ forever */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #include "dns.h" #define MAX_CPU_SECONDS 1 #define TEST_NAME "dns-spin-test" static void fail(const char *fmt, ...) __attribute__((format(printf, 1, 2), noreturn)); static void unresolved(const char *fmt, ...) __attribute__((format(printf, 1, 2), noreturn)); static void stdlib_fail(const char *msg) __attribute__((noreturn)); static void handle(int sig) __attribute__((noreturn)); void stdlib_fail(const char *msg) { perror(msg); printf("UNRESOLVED: " TEST_NAME " (stdlib failure)\n"); exit(77); } void unresolved(const char *fmt, ...) { va_list ap; printf("UNRESOLVED: " TEST_NAME ": "); va_start(ap, fmt); vprintf(fmt, ap); va_end(ap); printf("\n"); exit(77); } void fail(const char *fmt, ...) { va_list ap; va_start(ap, fmt); vprintf(fmt, ap); va_end(ap); printf("\n"); exit(EXIT_FAILURE); } void handle(AVAHI_GCC_UNUSED int sig) { fail("Interrupted after %d second of CPU time", MAX_CPU_SECONDS); } #define TRY_EXCEPT(cmd, badresult) \ do { \ if ((cmd) == (badresult)) \ unresolved("%s returned %s", #cmd, #badresult); \ } while (0) int main(AVAHI_GCC_UNUSED int argc, AVAHI_GCC_UNUSED char *argv[]) { struct itimerval itval; AvahiDnsPacket *packet; char name[512]; int ret; uint8_t badrr[] = { 0xC0, AVAHI_DNS_PACKET_HEADER_SIZE, /* self-referential QNAME pointer */ 0, 1, /* QTYPE A (host addr) */ 0, 1, /* QCLASS IN (internet/ipv4) */ }; if (signal(SIGVTALRM, handle) == SIG_ERR) stdlib_fail("signal(SIGVTALRM)"); memset(&itval, 0, sizeof(itval)); itval.it_value.tv_sec = MAX_CPU_SECONDS; if (setitimer(ITIMER_VIRTUAL, &itval, NULL) == -1) stdlib_fail("setitimer()"); TRY_EXCEPT(packet = avahi_dns_packet_new_query(512), NULL); TRY_EXCEPT(avahi_dns_packet_append_bytes(packet, badrr, sizeof(badrr)), NULL); /* This is expected to fail (if it returns) */ ret = avahi_dns_packet_consume_name(packet, name, sizeof(name)); if (ret != -1) fail("avahi_dns_packet_consume_name() returned %d; -1 was expected", ret); return EXIT_SUCCESS; } /* vim:ts=4:sw=4:et */