Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 1 | #undef NDEBUG |
| 2 | #include <stdio.h> |
| 3 | #include <stdlib.h> |
| 4 | #include <sys/types.h> |
| 5 | #include <string.h> |
| 6 | #include <assert.h> |
| 7 | |
| 8 | #include <T.h> |
| 9 | |
| 10 | uint8_t buf1[] = { |
| 11 | 32 | 16, /* [UNIVERSAL 16], constructed */ |
| 12 | 128, /* L */ |
| 13 | /* a INTEGER */ |
| 14 | 2, /* [UNIVERSAL 2] */ |
| 15 | 2, /* L */ |
| 16 | 150, |
| 17 | 70, |
Lev Walkin | 188ed2c | 2004-09-13 08:31:01 +0000 | [diff] [blame] | 18 | /* b [2] IMPLICIT BOOLEAN */ |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 19 | 128 | 2, /* [2] */ |
| 20 | 1, /* L */ |
| 21 | 0xff, |
| 22 | /* c NULL */ |
| 23 | 5, /* [UNIVERSAL 5] */ |
| 24 | 0, /* L */ |
| 25 | /* d ENUMERATED */ |
| 26 | 10, /* [UNIVERSAL 10] */ |
| 27 | 1, /* L */ |
| 28 | 222, |
Lev Walkin | 188ed2c | 2004-09-13 08:31:01 +0000 | [diff] [blame] | 29 | /* e OCTET STRING */ |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 30 | 4, /* [UNIVERSAL 4] */ |
| 31 | 3, /* L */ |
| 32 | 'x', |
| 33 | 'y', |
| 34 | 'z', |
Lev Walkin | 188ed2c | 2004-09-13 08:31:01 +0000 | [diff] [blame] | 35 | /* |
| 36 | * X.690 specifies that inner structures must be tagged by |
| 37 | * stripping off the outer tag for each subsequent level. |
| 38 | */ |
| 39 | /* f [5] IMPLICIT VisibleString */ |
| 40 | 128 | 32 | 5, /* [5], constructed */ |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 41 | 128, /* L indefinite */ |
Lev Walkin | 188ed2c | 2004-09-13 08:31:01 +0000 | [diff] [blame] | 42 | 26, /* [UNIVERSAL 26] (VisibleString), primitive */ |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 43 | 2, |
| 44 | 'l', |
| 45 | 'o', |
Lev Walkin | 188ed2c | 2004-09-13 08:31:01 +0000 | [diff] [blame] | 46 | 32 | 26, /* [UNIVERSAL 26], recursively constructed */ |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 47 | 128, |
Lev Walkin | 188ed2c | 2004-09-13 08:31:01 +0000 | [diff] [blame] | 48 | 4, /* [UNIVERSAL 4] (OCTET STRING), primitive */ |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 49 | 1, |
| 50 | 'v', |
Lev Walkin | 188ed2c | 2004-09-13 08:31:01 +0000 | [diff] [blame] | 51 | 4, /* [UNIVERSAL 4], primitive */ |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 52 | 2, |
| 53 | 'e', |
| 54 | '_', |
| 55 | 0, |
| 56 | 0, |
Lev Walkin | 188ed2c | 2004-09-13 08:31:01 +0000 | [diff] [blame] | 57 | 26, /* [UNIVERSAL 26], primitive */ |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 58 | 2, |
| 59 | 'i', |
| 60 | 't', |
| 61 | 0, |
| 62 | 0, |
| 63 | /* g BIT STRING */ |
| 64 | 3, /* [UNIVERSAL 3], primitive */ |
| 65 | 3, /* L */ |
| 66 | 2, /* Skip 2 bits */ |
| 67 | 147, |
| 68 | 150, /* => 148 */ |
Lev Walkin | 188ed2c | 2004-09-13 08:31:01 +0000 | [diff] [blame] | 69 | /* h [7] BIT STRING */ |
| 70 | 128 | 32 | 7, /* [7], constructed */ |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 71 | 128, /* L indefinite */ |
| 72 | 3, /* [UNIVERSAL 3], primitive */ |
| 73 | 3, /* L */ |
| 74 | 0, /* Skip 0 bits */ |
| 75 | 140, |
| 76 | 141, |
| 77 | 3, /* [UNIVERSAL 3], primitive */ |
| 78 | 2, /* L */ |
| 79 | 1, /* Skip 1 bit */ |
| 80 | 143, /* => 142 */ |
Lev Walkin | 188ed2c | 2004-09-13 08:31:01 +0000 | [diff] [blame] | 81 | 0, /* End of h */ |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 82 | 0, |
| 83 | 0, /* End of the whole structure */ |
| 84 | 0, |
| 85 | /* Three bytes of planned leftover */ |
| 86 | 111, 222, 223 |
| 87 | }; |
| 88 | |
| 89 | static void |
Lev Walkin | 1715b32 | 2013-03-28 04:02:13 -0700 | [diff] [blame] | 90 | check(int is_ok, uint8_t *buf, size_t size, size_t consumed) { |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 91 | T_t t, *tp; |
Lev Walkin | 90bf7ae | 2004-10-20 15:46:56 +0000 | [diff] [blame] | 92 | asn_dec_rval_t rval; |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 93 | |
| 94 | tp = memset(&t, 0, sizeof(t)); |
| 95 | |
Lev Walkin | 1715b32 | 2013-03-28 04:02:13 -0700 | [diff] [blame] | 96 | fprintf(stderr, "Buf %p (%zd)\n", buf, size); |
Lev Walkin | c7400c5 | 2004-09-29 13:14:36 +0000 | [diff] [blame] | 97 | rval = ber_decode(0, &asn_DEF_T, (void **)&tp, buf, size); |
Lev Walkin | 1715b32 | 2013-03-28 04:02:13 -0700 | [diff] [blame] | 98 | fprintf(stderr, "Returned code %d, consumed %zd, expected %zd\n", |
| 99 | (int)rval.code, rval.consumed, consumed); |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 100 | |
| 101 | if(is_ok) { |
| 102 | assert(rval.code == RC_OK); |
| 103 | assert(rval.consumed == consumed); |
| 104 | |
Lev Walkin | 59b176e | 2005-11-26 11:25:14 +0000 | [diff] [blame] | 105 | assert(strcmp((char *)t.e->buf, "xyz") == 0); |
| 106 | assert(strcmp((char *)t.f->buf, "love_it") == 0); |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 107 | |
Lev Walkin | bbd9325 | 2004-10-12 05:57:23 +0000 | [diff] [blame] | 108 | assert(t.g->size == 2); |
| 109 | assert(t.g->bits_unused == 2); |
Lev Walkin | e7727d5 | 2005-02-25 12:16:59 +0000 | [diff] [blame] | 110 | fprintf(stderr, "%d %d\n", t.g->buf[0], t.g->buf[1]); |
Lev Walkin | bbd9325 | 2004-10-12 05:57:23 +0000 | [diff] [blame] | 111 | assert(t.g->buf[0] == 147); |
| 112 | assert(t.g->buf[1] != 150); |
| 113 | assert(t.g->buf[1] == 148); |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 114 | |
Lev Walkin | bbd9325 | 2004-10-12 05:57:23 +0000 | [diff] [blame] | 115 | assert(t.h->size == 3); |
| 116 | assert(t.h->bits_unused == 1); |
| 117 | assert(t.h->buf[0] == 140); |
| 118 | assert(t.h->buf[1] == 141); |
| 119 | assert(t.h->buf[2] == 142); |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 120 | } else { |
| 121 | if(rval.code == RC_OK) { |
| 122 | assert(t.a.size != 2 |
| 123 | || !t.d |
| 124 | || t.d->size != 1 |
| 125 | || !t.e |
| 126 | || t.e->size != 3 |
| 127 | || !t.f |
| 128 | || t.f->size != 7 |
| 129 | || !t.g |
Lev Walkin | bbd9325 | 2004-10-12 05:57:23 +0000 | [diff] [blame] | 130 | || t.g->size != 2 |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 131 | || !t.h |
Lev Walkin | bbd9325 | 2004-10-12 05:57:23 +0000 | [diff] [blame] | 132 | || t.h->size != 3 |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 133 | ); |
| 134 | } |
Lev Walkin | 1715b32 | 2013-03-28 04:02:13 -0700 | [diff] [blame] | 135 | fprintf(stderr, "%zd %zd\n", rval.consumed, consumed); |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 136 | assert(rval.consumed <= consumed); |
| 137 | } |
| 138 | |
Lev Walkin | 8d99d7b | 2017-08-25 01:06:00 -0700 | [diff] [blame] | 139 | ASN_STRUCT_RESET(asn_DEF_T, &t); |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 140 | } |
| 141 | |
| 142 | static void |
Lev Walkin | 1715b32 | 2013-03-28 04:02:13 -0700 | [diff] [blame] | 143 | try_corrupt(uint8_t *buf, size_t size, int allow_consume) { |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 144 | uint8_t *tmp; |
| 145 | int i; |
| 146 | |
| 147 | fprintf(stderr, "\nCorrupting...\n"); |
| 148 | |
| 149 | tmp = alloca(size); |
| 150 | |
| 151 | for(i = 0; i < 1000; i++) { |
| 152 | int loc; |
| 153 | memcpy(tmp, buf, size); |
| 154 | |
| 155 | /* Corrupt random _non-value_ location. */ |
| 156 | do { loc = random() % size; } while( |
| 157 | loc == 44 /* bit skips */ |
| 158 | || loc == 51 /* bit skips */ |
| 159 | || loc == 56 /* bit skips */ |
| 160 | || tmp[loc] >= 70); |
| 161 | do { tmp[loc] = buf[loc] ^ random(); } while( |
| 162 | (tmp[loc] == buf[loc]) |
| 163 | || (buf[loc] == 0 && tmp[loc] == 0x80)); |
| 164 | |
| 165 | fprintf(stderr, "\nTry %d: corrupting byte %d (%d->%d)\n", |
| 166 | i, loc, buf[loc], tmp[loc]); |
| 167 | |
| 168 | check(0, tmp, size, allow_consume); |
| 169 | } |
| 170 | } |
| 171 | |
| 172 | static void |
Lev Walkin | d9bd775 | 2004-06-05 08:17:50 +0000 | [diff] [blame] | 173 | partial_read(uint8_t *buf, size_t size) { |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 174 | T_t t, *tp; |
Lev Walkin | 90bf7ae | 2004-10-20 15:46:56 +0000 | [diff] [blame] | 175 | asn_dec_rval_t rval; |
Lev Walkin | d9bd775 | 2004-06-05 08:17:50 +0000 | [diff] [blame] | 176 | size_t i1, i2; |
Lev Walkin | b4eb8b5 | 2004-08-16 07:02:39 +0000 | [diff] [blame] | 177 | uint8_t *tbuf1 = alloca(size); |
| 178 | uint8_t *tbuf2 = alloca(size); |
| 179 | uint8_t *tbuf3 = alloca(size); |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 180 | |
| 181 | fprintf(stderr, "\nPartial read sequence...\n"); |
| 182 | |
| 183 | /* |
| 184 | * Divide the space (size) into three blocks in various combinations: |
| 185 | * |<----->i1<----->i2<----->| |
| 186 | * ^ buf ^ buf+size |
| 187 | * Try to read block by block. |
| 188 | */ |
| 189 | for(i1 = 0; i1 < size; i1++) { |
| 190 | for(i2 = i1; i2 < size; i2++) { |
| 191 | uint8_t *chunk1 = buf; |
Lev Walkin | d9bd775 | 2004-06-05 08:17:50 +0000 | [diff] [blame] | 192 | size_t size1 = i1; |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 193 | uint8_t *chunk2 = buf + size1; |
Lev Walkin | d9bd775 | 2004-06-05 08:17:50 +0000 | [diff] [blame] | 194 | size_t size2 = i2 - i1; |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 195 | uint8_t *chunk3 = buf + size1 + size2; |
Lev Walkin | d9bd775 | 2004-06-05 08:17:50 +0000 | [diff] [blame] | 196 | size_t size3 = size - size1 - size2; |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 197 | |
| 198 | fprintf(stderr, "\n%d:{%d, %d, %d}...\n", |
Lev Walkin | b4eb8b5 | 2004-08-16 07:02:39 +0000 | [diff] [blame] | 199 | (int)size, (int)size1, (int)size2, (int)size3); |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 200 | |
Lev Walkin | b4eb8b5 | 2004-08-16 07:02:39 +0000 | [diff] [blame] | 201 | memset(tbuf1, 0, size); |
| 202 | memset(tbuf2, 0, size); |
| 203 | memset(tbuf3, 0, size); |
| 204 | memcpy(tbuf1, chunk1, size1); |
| 205 | memcpy(tbuf2, chunk2, size2); |
| 206 | memcpy(tbuf3, chunk3, size3); |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 207 | |
| 208 | tp = memset(&t, 0, sizeof(t)); |
| 209 | |
Lev Walkin | b4eb8b5 | 2004-08-16 07:02:39 +0000 | [diff] [blame] | 210 | fprintf(stderr, "=> Chunk 1 (%d):\n", (int)size1); |
Lev Walkin | c7400c5 | 2004-09-29 13:14:36 +0000 | [diff] [blame] | 211 | rval = ber_decode(0, &asn_DEF_T, (void **)&tp, |
Lev Walkin | b4eb8b5 | 2004-08-16 07:02:39 +0000 | [diff] [blame] | 212 | tbuf1, size1); |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 213 | assert(rval.code == RC_WMORE); |
| 214 | assert(rval.consumed <= size1); |
| 215 | if(rval.consumed < size1) { |
| 216 | int leftover = size1 - rval.consumed; |
Lev Walkin | b4eb8b5 | 2004-08-16 07:02:39 +0000 | [diff] [blame] | 217 | memcpy(tbuf2, tbuf1 + rval.consumed, leftover); |
| 218 | memcpy(tbuf2 + leftover, chunk2, size2); |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 219 | size2 += leftover; |
| 220 | } |
| 221 | |
Lev Walkin | b4eb8b5 | 2004-08-16 07:02:39 +0000 | [diff] [blame] | 222 | fprintf(stderr, "=> Chunk 2 (%d):\n", (int)size2); |
Lev Walkin | c7400c5 | 2004-09-29 13:14:36 +0000 | [diff] [blame] | 223 | rval = ber_decode(0, &asn_DEF_T, (void **)&tp, |
Lev Walkin | b4eb8b5 | 2004-08-16 07:02:39 +0000 | [diff] [blame] | 224 | tbuf2, size2); |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 225 | assert(rval.code == RC_WMORE); |
| 226 | assert(rval.consumed <= size2); |
| 227 | if(rval.consumed < size2) { |
| 228 | int leftover = size2 - rval.consumed; |
Lev Walkin | b4eb8b5 | 2004-08-16 07:02:39 +0000 | [diff] [blame] | 229 | memcpy(tbuf3, tbuf2 + rval.consumed, leftover); |
| 230 | memcpy(tbuf3 + leftover, chunk3, size3); |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 231 | size3 += leftover; |
| 232 | } |
| 233 | |
Lev Walkin | b4eb8b5 | 2004-08-16 07:02:39 +0000 | [diff] [blame] | 234 | fprintf(stderr, "=> Chunk 3 (%d):\n", (int)size3); |
Lev Walkin | c7400c5 | 2004-09-29 13:14:36 +0000 | [diff] [blame] | 235 | rval = ber_decode(0, &asn_DEF_T, (void **)&tp, |
Lev Walkin | b4eb8b5 | 2004-08-16 07:02:39 +0000 | [diff] [blame] | 236 | tbuf3, size3); |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 237 | assert(rval.code == RC_OK); |
| 238 | assert(rval.consumed == size3); |
| 239 | |
Lev Walkin | 8d99d7b | 2017-08-25 01:06:00 -0700 | [diff] [blame] | 240 | ASN_STRUCT_RESET(asn_DEF_T, &t); |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 241 | } |
| 242 | } |
| 243 | } |
| 244 | |
| 245 | int |
| 246 | main(int ac, char **av) { |
| 247 | |
Lev Walkin | d9bd775 | 2004-06-05 08:17:50 +0000 | [diff] [blame] | 248 | (void)ac; /* Unused argument */ |
| 249 | (void)av; /* Unused argument */ |
| 250 | |
Lev Walkin | f15320b | 2004-06-03 03:38:44 +0000 | [diff] [blame] | 251 | /* Check that the full buffer may be decoded normally */ |
| 252 | check(1, buf1, sizeof(buf1), sizeof(buf1) - 3); |
| 253 | |
| 254 | /* Check that some types of buffer corruptions will lead to failure */ |
| 255 | try_corrupt(buf1, sizeof(buf1) - 3, sizeof(buf1) - 3); |
| 256 | |
| 257 | /* Split the buffer in parts and check decoder restartability */ |
| 258 | partial_read(buf1, sizeof(buf1) - 3); |
| 259 | |
| 260 | return 0; |
| 261 | } |