| | 1 | /* $Id$ */ |
|---|
| | 2 | |
|---|
| | 3 | /*** |
|---|
| | 4 | This file is part of avahi. |
|---|
| | 5 | |
|---|
| | 6 | avahi is free software; you can redistribute it and/or modify it |
|---|
| | 7 | under the terms of the GNU Lesser General Public License as |
|---|
| | 8 | published by the Free Software Foundation; either version 2.1 of the |
|---|
| | 9 | License, or (at your option) any later version. |
|---|
| | 10 | |
|---|
| | 11 | avahi is distributed in the hope that it will be useful, but WITHOUT |
|---|
| | 12 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
|---|
| | 13 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General |
|---|
| | 14 | Public License for more details. |
|---|
| | 15 | |
|---|
| | 16 | You should have received a copy of the GNU Lesser General Public |
|---|
| | 17 | License along with avahi; if not, write to the Free Software |
|---|
| | 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 |
|---|
| | 19 | USA. |
|---|
| | 20 | ***/ |
|---|
| | 21 | |
|---|
| | 22 | /* Regression test for Avahi bug #84. |
|---|
| | 23 | * This program tests whether the avahi_dns_packet_consume_name function |
|---|
| | 24 | * returns (rather than spinning forever). For a function as simple as |
|---|
| | 25 | * avahi_dns_packet_consume_name, we assume that 1 second of CPU time ≈ forever |
|---|
| | 26 | */ |
|---|
| | 27 | |
|---|
| | 28 | #ifdef HAVE_CONFIG_H |
|---|
| | 29 | # include <config.h> |
|---|
| | 30 | #endif |
|---|
| | 31 | |
|---|
| | 32 | #include <string.h> |
|---|
| | 33 | #include <stdint.h> |
|---|
| | 34 | #include <stdio.h> |
|---|
| | 35 | #include <stdlib.h> |
|---|
| | 36 | #include <signal.h> |
|---|
| | 37 | #include <sys/time.h> |
|---|
| | 38 | |
|---|
| | 39 | #include "dns.h" |
|---|
| | 40 | |
|---|
| | 41 | #define MAX_CPU_SECONDS 1 |
|---|
| | 42 | |
|---|
| | 43 | #define TEST_NAME "dns-spin-test" |
|---|
| | 44 | |
|---|
| | 45 | static void fail(const char *fmt, ...) __attribute__((format(printf, 1, 2), noreturn)); |
|---|
| | 46 | static void unresolved(const char *fmt, ...) __attribute__((format(printf, 1, 2), noreturn)); |
|---|
| | 47 | static void stdlib_fail(const char *msg) __attribute__((noreturn)); |
|---|
| | 48 | static void handle(int sig) __attribute__((noreturn)); |
|---|
| | 49 | |
|---|
| | 50 | void stdlib_fail(const char *msg) { |
|---|
| | 51 | perror(msg); |
|---|
| | 52 | |
|---|
| | 53 | printf("UNRESOLVED: " TEST_NAME " (stdlib failure)\n"); |
|---|
| | 54 | |
|---|
| | 55 | exit(77); |
|---|
| | 56 | } |
|---|
| | 57 | |
|---|
| | 58 | void unresolved(const char *fmt, ...) { |
|---|
| | 59 | va_list ap; |
|---|
| | 60 | |
|---|
| | 61 | printf("UNRESOLVED: " TEST_NAME ": "); |
|---|
| | 62 | va_start(ap, fmt); |
|---|
| | 63 | vprintf(fmt, ap); |
|---|
| | 64 | va_end(ap); |
|---|
| | 65 | printf("\n"); |
|---|
| | 66 | |
|---|
| | 67 | exit(77); |
|---|
| | 68 | } |
|---|
| | 69 | |
|---|
| | 70 | void fail(const char *fmt, ...) { |
|---|
| | 71 | va_list ap; |
|---|
| | 72 | |
|---|
| | 73 | va_start(ap, fmt); |
|---|
| | 74 | vprintf(fmt, ap); |
|---|
| | 75 | va_end(ap); |
|---|
| | 76 | printf("\n"); |
|---|
| | 77 | |
|---|
| | 78 | exit(EXIT_FAILURE); |
|---|
| | 79 | } |
|---|
| | 80 | |
|---|
| | 81 | void handle(AVAHI_GCC_UNUSED int sig) { |
|---|
| | 82 | fail("Interrupted after %d second of CPU time", MAX_CPU_SECONDS); |
|---|
| | 83 | } |
|---|
| | 84 | |
|---|
| | 85 | #define TRY_EXCEPT(cmd, badresult) \ |
|---|
| | 86 | do { \ |
|---|
| | 87 | if ((cmd) == (badresult)) \ |
|---|
| | 88 | unresolved("%s returned %s", #cmd, #badresult); \ |
|---|
| | 89 | } while (0) |
|---|
| | 90 | |
|---|
| | 91 | int main(AVAHI_GCC_UNUSED int argc, AVAHI_GCC_UNUSED char *argv[]) { |
|---|
| | 92 | struct itimerval itval; |
|---|
| | 93 | AvahiDnsPacket *packet; |
|---|
| | 94 | char name[512]; |
|---|
| | 95 | int ret; |
|---|
| | 96 | uint8_t badrr[] = { |
|---|
| | 97 | 0xC0, AVAHI_DNS_PACKET_HEADER_SIZE, /* self-referential QNAME pointer */ |
|---|
| | 98 | 0, 1, /* QTYPE A (host addr) */ |
|---|
| | 99 | 0, 1, /* QCLASS IN (internet/ipv4) */ |
|---|
| | 100 | }; |
|---|
| | 101 | |
|---|
| | 102 | if (signal(SIGVTALRM, handle) == SIG_ERR) |
|---|
| | 103 | stdlib_fail("signal(SIGVTALRM)"); |
|---|
| | 104 | |
|---|
| | 105 | memset(&itval, 0, sizeof(itval)); |
|---|
| | 106 | itval.it_value.tv_sec = MAX_CPU_SECONDS; |
|---|
| | 107 | |
|---|
| | 108 | if (setitimer(ITIMER_VIRTUAL, &itval, NULL) == -1) |
|---|
| | 109 | stdlib_fail("setitimer()"); |
|---|
| | 110 | |
|---|
| | 111 | TRY_EXCEPT(packet = avahi_dns_packet_new_query(512), NULL); |
|---|
| | 112 | TRY_EXCEPT(avahi_dns_packet_append_bytes(packet, badrr, sizeof(badrr)), NULL); |
|---|
| | 113 | |
|---|
| | 114 | /* This is expected to fail (if it returns) */ |
|---|
| | 115 | ret = avahi_dns_packet_consume_name(packet, name, sizeof(name)); |
|---|
| | 116 | |
|---|
| | 117 | if (ret != -1) |
|---|
| | 118 | fail("avahi_dns_packet_consume_name() returned %d; -1 was expected", ret); |
|---|
| | 119 | |
|---|
| | 120 | return EXIT_SUCCESS; |
|---|
| | 121 | } |
|---|
| | 122 | |
|---|
| | 123 | /* vim:ts=4:sw=4:et |
|---|
| | 124 | */ |