11 32 | 16, /* [UNIVERSAL 16], constructed */
14 2, /* [UNIVERSAL 2] */
18 /* b [2] IMPLICIT BOOLEAN */
23 5, /* [UNIVERSAL 5] */
26 10, /* [UNIVERSAL 10] */
30 4, /* [UNIVERSAL 4] */
36 * X.690 specifies that inner structures must be tagged by
37 * stripping off the outer tag for each subsequent level.
39 /* f [5] IMPLICIT VisibleString */
40 128 | 32 | 5, /* [5], constructed */
41 128, /* L indefinite */
42 26, /* [UNIVERSAL 26] (VisibleString), primitive */
46 32 | 26, /* [UNIVERSAL 26], recursively constructed */
48 4, /* [UNIVERSAL 4] (OCTET STRING), primitive */
51 4, /* [UNIVERSAL 4], primitive */
57 26, /* [UNIVERSAL 26], primitive */
64 3, /* [UNIVERSAL 3], primitive */
69 /* h [7] BIT STRING */
70 128 | 32 | 7, /* [7], constructed */
71 128, /* L indefinite */
72 3, /* [UNIVERSAL 3], primitive */
77 3, /* [UNIVERSAL 3], primitive */
83 0, /* End of the whole structure */
85 /* Three bytes of planned leftover */
90 check(int is_ok, uint8_t *buf, size_t size, size_t consumed) {
94 tp = memset(&t, 0, sizeof(t));
96 fprintf(stderr, "Buf %p (%zd)\n", buf, size);
97 rval = ber_decode(0, &asn_DEF_T, (void **)&tp, buf, size);
98 fprintf(stderr, "Returned code %d, consumed %zd, expected %zd\n",
99 (int)rval.code, rval.consumed, consumed);
102 assert(rval.code == RC_OK);
103 assert(rval.consumed == consumed);
105 assert(strcmp((char *)t.e->buf, "xyz") == 0);
106 assert(strcmp((char *)t.f->buf, "love_it") == 0);
108 assert(t.g->size == 2);
109 assert(t.g->bits_unused == 2);
110 fprintf(stderr, "%d %d\n", t.g->buf[0], t.g->buf[1]);
111 assert(t.g->buf[0] == 147);
112 assert(t.g->buf[1] != 150);
113 assert(t.g->buf[1] == 148);
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);
121 if(rval.code == RC_OK) {
135 fprintf(stderr, "%zd %zd\n", rval.consumed, consumed);
136 assert(rval.consumed <= consumed);
139 ASN_STRUCT_RESET(asn_DEF_T, &t);
143 try_corrupt(uint8_t *buf, size_t size, int allow_consume) {
146 fprintf(stderr, "\nCorrupting...\n");
148 for(int i = 0; i < 1000; i++) {
150 memcpy(tmp, buf, size);
152 /* Corrupt random _non-value_ location. */
153 do { loc = random() % size; } while(
154 loc == 44 /* bit skips */
155 || loc == 51 /* bit skips */
156 || loc == 56 /* bit skips */
158 do { tmp[loc] = buf[loc] ^ random(); } while(
159 (tmp[loc] == buf[loc])
160 || (buf[loc] == 0 && tmp[loc] == 0x80));
162 fprintf(stderr, "\nTry %d: corrupting byte %d (%d->%d)\n",
163 i, loc, buf[loc], tmp[loc]);
165 check(0, tmp, size, allow_consume);
170 partial_read(uint8_t *buf, size_t size) {
177 fprintf(stderr, "\nPartial read sequence...\n");
180 * Divide the space (size) into three blocks in various combinations:
181 * |<----->i1<----->i2<----->|
183 * Try to read block by block.
185 for(size_t i1 = 0; i1 < size; i1++) {
186 for(size_t i2 = i1; i2 < size; i2++) {
187 uint8_t *chunk1 = buf;
189 uint8_t *chunk2 = buf + size1;
190 size_t size2 = i2 - i1;
191 uint8_t *chunk3 = buf + size1 + size2;
192 size_t size3 = size - size1 - size2;
194 fprintf(stderr, "\n%d:{%d, %d, %d}...\n",
195 (int)size, (int)size1, (int)size2, (int)size3);
197 memset(tbuf1, 0, size);
198 memset(tbuf2, 0, size);
199 memset(tbuf3, 0, size);
200 memcpy(tbuf1, chunk1, size1);
201 memcpy(tbuf2, chunk2, size2);
202 memcpy(tbuf3, chunk3, size3);
204 tp = memset(&t, 0, sizeof(t));
206 fprintf(stderr, "=> Chunk 1 (%d):\n", (int)size1);
207 rval = ber_decode(0, &asn_DEF_T, (void **)&tp,
209 assert(rval.code == RC_WMORE);
210 assert(rval.consumed <= size1);
211 if(rval.consumed < size1) {
212 int leftover = size1 - rval.consumed;
213 memcpy(tbuf2, tbuf1 + rval.consumed, leftover);
214 memcpy(tbuf2 + leftover, chunk2, size2);
218 fprintf(stderr, "=> Chunk 2 (%d):\n", (int)size2);
219 rval = ber_decode(0, &asn_DEF_T, (void **)&tp,
221 assert(rval.code == RC_WMORE);
222 assert(rval.consumed <= size2);
223 if(rval.consumed < size2) {
224 int leftover = size2 - rval.consumed;
225 memcpy(tbuf3, tbuf2 + rval.consumed, leftover);
226 memcpy(tbuf3 + leftover, chunk3, size3);
230 fprintf(stderr, "=> Chunk 3 (%d):\n", (int)size3);
231 rval = ber_decode(0, &asn_DEF_T, (void **)&tp,
233 assert(rval.code == RC_OK);
234 assert(rval.consumed == size3);
236 ASN_STRUCT_RESET(asn_DEF_T, &t);
242 main(int ac, char **av) {
244 (void)ac; /* Unused argument */
245 (void)av; /* Unused argument */
247 /* Check that the full buffer may be decoded normally */
248 check(1, buf1, sizeof(buf1), sizeof(buf1) - 3);
250 /* Check that some types of buffer corruptions will lead to failure */
251 try_corrupt(buf1, sizeof(buf1) - 3, sizeof(buf1) - 3);
253 /* Split the buffer in parts and check decoder restartability */
254 partial_read(buf1, sizeof(buf1) - 3);