Return to unit1655.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / curl / tests / unit |
1.1 ! misho 1: /*************************************************************************** ! 2: * _ _ ____ _ ! 3: * Project ___| | | | _ \| | ! 4: * / __| | | | |_) | | ! 5: * | (__| |_| | _ <| |___ ! 6: * \___|\___/|_| \_\_____| ! 7: * ! 8: * Copyright (C) 2019 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. ! 9: * ! 10: * This software is licensed as described in the file COPYING, which ! 11: * you should have received as part of this distribution. The terms ! 12: * are also available at https://curl.haxx.se/docs/copyright.html. ! 13: * ! 14: * You may opt to use, copy, modify, merge, publish, distribute and/or sell ! 15: * copies of the Software, and permit persons to whom the Software is ! 16: * furnished to do so, under the terms of the COPYING file. ! 17: * ! 18: * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY ! 19: * KIND, either express or implied. ! 20: * ! 21: ***************************************************************************/ ! 22: #include "curlcheck.h" ! 23: ! 24: #include "doh.h" /* from the lib dir */ ! 25: ! 26: static CURLcode unit_setup(void) ! 27: { ! 28: /* whatever you want done first */ ! 29: return CURLE_OK; ! 30: } ! 31: ! 32: static void unit_stop(void) ! 33: { ! 34: /* done before shutting down and exiting */ ! 35: } ! 36: ! 37: #ifndef CURL_DISABLE_DOH ! 38: ! 39: UNITTEST_START ! 40: ! 41: /* ! 42: * Prove detection of write overflow using a short buffer and a name ! 43: * of maximal valid length. ! 44: * ! 45: * Prove detection of other invalid input. ! 46: */ ! 47: do { ! 48: const char *max = ! 49: /* ..|....1.........2.........3.........4.........5.........6... */ ! 50: /* 3456789012345678901234567890123456789012345678901234567890123 */ ! 51: "this.is.a.maximum-length.hostname." /* 34: 34 */ ! 52: "with-no-label-of-greater-length-than-the-sixty-three-characters." ! 53: /* 64: 98 */ ! 54: "specified.in.the.RFCs." /* 22: 120 */ ! 55: "and.with.a.QNAME.encoding.whose.length.is.exactly." /* 50: 170 */ ! 56: "the.maximum.length.allowed." /* 27: 197 */ ! 57: "that.is.two-hundred.and.fifty-six." /* 34: 231 */ ! 58: "including.the.last.null." /* 24: 255 */ ! 59: ""; ! 60: const char *toolong = ! 61: /* ..|....1.........2.........3.........4.........5.........6... */ ! 62: /* 3456789012345678901234567890123456789012345678901234567890123 */ ! 63: "here.is.a.hostname.which.is.just.barely.too.long." /* 49: 49 */ ! 64: "to.be.encoded.as.a.QNAME.of.the.maximum.allowed.length." ! 65: /* 55: 104 */ ! 66: "which.is.256.including.a.final.zero-length.label." /* 49: 153 */ ! 67: "representing.the.root.node.so.that.a.name.with." /* 47: 200 */ ! 68: "a.trailing.dot.may.have.up.to." /* 30: 230 */ ! 69: "255.characters.never.more." /* 26: 256 */ ! 70: ""; ! 71: const char *emptylabel = ! 72: "this.is.an.otherwise-valid.hostname." ! 73: ".with.an.empty.label."; ! 74: const char *outsizelabel = ! 75: "this.is.an.otherwise-valid.hostname." ! 76: "with-a-label-of-greater-length-than-the-sixty-three-characters-" ! 77: "specified.in.the.RFCs."; ! 78: int i; ! 79: ! 80: struct test { ! 81: const char *name; ! 82: const DOHcode expected_result; ! 83: }; ! 84: ! 85: /* plays the role of struct dnsprobe in urldata.h */ ! 86: struct demo { ! 87: unsigned char dohbuffer[255 + 16]; /* deliberately short buffer */ ! 88: unsigned char canary1; ! 89: unsigned char canary2; ! 90: unsigned char canary3; ! 91: }; ! 92: ! 93: const struct test playlist[4] = { ! 94: { toolong, DOH_DNS_NAME_TOO_LONG }, /* expect early failure */ ! 95: { emptylabel, DOH_DNS_BAD_LABEL }, /* also */ ! 96: { outsizelabel, DOH_DNS_BAD_LABEL }, /* also */ ! 97: { max, DOH_OK } /* expect buffer overwrite */ ! 98: }; ! 99: ! 100: for(i = 0; i < (int)(sizeof(playlist)/sizeof(*playlist)); i++) { ! 101: const char *name = playlist[i].name; ! 102: size_t olen = 100000; ! 103: struct demo victim; ! 104: DOHcode d; ! 105: ! 106: victim.canary1 = 87; /* magic numbers, arbritrarily picked */ ! 107: victim.canary2 = 35; ! 108: victim.canary3 = 41; ! 109: d = doh_encode(name, DNS_TYPE_A, victim.dohbuffer, ! 110: sizeof(struct demo), /* allow room for overflow */ ! 111: &olen); ! 112: ! 113: fail_unless(d == playlist[i].expected_result, ! 114: "result returned was not as expected"); ! 115: if(d == playlist[i].expected_result) { ! 116: if(name == max) { ! 117: fail_if(victim.canary1 == 87, ! 118: "demo one-byte buffer overwrite did not happen"); ! 119: } ! 120: else { ! 121: fail_unless(victim.canary1 == 87, ! 122: "one-byte buffer overwrite has happened"); ! 123: } ! 124: fail_unless(victim.canary2 == 35, ! 125: "two-byte buffer overwrite has happened"); ! 126: fail_unless(victim.canary3 == 41, ! 127: "three-byte buffer overwrite has happened"); ! 128: } ! 129: else { ! 130: if(d == DOH_OK) { ! 131: fail_unless(olen <= sizeof(victim.dohbuffer), "wrote outside bounds"); ! 132: fail_unless(olen > strlen(name), "unrealistic low size"); ! 133: } ! 134: } ! 135: } ! 136: } while(0); ! 137: ! 138: /* run normal cases and try to trigger buffer length related errors */ ! 139: do { ! 140: DNStype dnstype = DNS_TYPE_A; ! 141: unsigned char buffer[128]; ! 142: const size_t buflen = sizeof(buffer); ! 143: const size_t magic1 = 9765; ! 144: size_t olen1 = magic1; ! 145: const char *sunshine1 = "a.com"; ! 146: const char *dotshine1 = "a.com."; ! 147: const char *sunshine2 = "aa.com"; ! 148: size_t olen2; ! 149: DOHcode ret2; ! 150: size_t olen; ! 151: ! 152: DOHcode ret = doh_encode(sunshine1, dnstype, buffer, buflen, &olen1); ! 153: fail_unless(ret == DOH_OK, "sunshine case 1 should pass fine"); ! 154: fail_if(olen1 == magic1, "olen has not been assigned properly"); ! 155: fail_unless(olen1 > strlen(sunshine1), "bad out length"); ! 156: ! 157: /* with a trailing dot, the response should have the same length */ ! 158: olen2 = magic1; ! 159: ret2 = doh_encode(dotshine1, dnstype, buffer, buflen, &olen2); ! 160: fail_unless(ret2 == DOH_OK, "dotshine case should pass fine"); ! 161: fail_if(olen2 == magic1, "olen has not been assigned properly"); ! 162: fail_unless(olen1 == olen2, "olen should not grow for a trailing dot"); ! 163: ! 164: /* add one letter, the response should be one longer */ ! 165: olen2 = magic1; ! 166: ret2 = doh_encode(sunshine2, dnstype, buffer, buflen, &olen2); ! 167: fail_unless(ret2 == DOH_OK, "sunshine case 2 should pass fine"); ! 168: fail_if(olen2 == magic1, "olen has not been assigned properly"); ! 169: fail_unless(olen1 + 1 == olen2, "olen should grow with the hostname"); ! 170: ! 171: /* pass a short buffer, should fail */ ! 172: ret = doh_encode(sunshine1, dnstype, buffer, olen1 - 1, &olen); ! 173: fail_if(ret == DOH_OK, "short buffer should have been noticed"); ! 174: ! 175: /* pass a minimum buffer, should succeed */ ! 176: ret = doh_encode(sunshine1, dnstype, buffer, olen1, &olen); ! 177: fail_unless(ret == DOH_OK, "minimal length buffer should be long enough"); ! 178: fail_unless(olen == olen1, "bad buffer length"); ! 179: } while(0); ! 180: UNITTEST_STOP ! 181: ! 182: #else /* CURL_DISABLE_DOH */ ! 183: ! 184: UNITTEST_START ! 185: { ! 186: return 1; /* nothing to do, just fail */ ! 187: } ! 188: UNITTEST_STOP ! 189: ! 190: #endif