NativeEnumerated.c vars NULL init and check
[com/asn1c.git] / tests / tests-c-compiler / check-src / check-25.-fwide-types.c
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,
18         /* b [2] IMPLICIT BOOLEAN */
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,
29         /* e OCTET STRING */
30         4,                      /* [UNIVERSAL 4] */
31         3,      /* L */
32         'x',
33         'y',
34         'z',
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 */
41         128,    /* L indefinite */
42                 26,     /* [UNIVERSAL 26] (VisibleString), primitive */
43                 2,
44   'l',
45   'o',
46                 32 | 26,        /* [UNIVERSAL 26], recursively constructed */
47                 128,
48                         4,      /* [UNIVERSAL 4] (OCTET STRING), primitive */
49                         1,
50   'v',
51                         4,      /* [UNIVERSAL 4], primitive */
52                         2,
53   'e',
54   '_',
55                 0,
56                 0,
57                 26,     /* [UNIVERSAL 26], primitive */
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 */
69         /* h [7] BIT STRING */
70         128 | 32 | 7,                   /* [7], constructed */
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 */
81         0,      /* End of h */
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
90 check(int is_ok, uint8_t *buf, size_t size, size_t consumed) {
91         T_t t, *tp;
92         asn_dec_rval_t rval;
93
94         tp = memset(&t, 0, sizeof(t));
95
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);
100
101         if(is_ok) {
102                 assert(rval.code == RC_OK);
103                 assert(rval.consumed == consumed);
104
105                 assert(strcmp((char *)t.e->buf, "xyz") == 0);
106                 assert(strcmp((char *)t.f->buf, "love_it") == 0);
107
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);
114
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);
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
130                         || t.g->size != 2
131                         || !t.h
132                         || t.h->size != 3
133                         );
134                 }
135                 fprintf(stderr, "%zd %zd\n", rval.consumed, consumed);
136                 assert(rval.consumed <= consumed);
137         }
138
139         ASN_STRUCT_RESET(asn_DEF_T, &t);
140 }
141
142 static void
143 try_corrupt(uint8_t *buf, size_t size, int allow_consume) {
144         uint8_t tmp[size];
145
146         fprintf(stderr, "\nCorrupting...\n");
147
148         for(int i = 0; i < 1000; i++) {
149                 int loc;
150                 memcpy(tmp, buf, size);
151
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 */
157                         || tmp[loc] >= 70);
158                 do { tmp[loc] = buf[loc] ^ random(); } while(
159                         (tmp[loc] == buf[loc])
160                         || (buf[loc] == 0 && tmp[loc] == 0x80));
161
162                 fprintf(stderr, "\nTry %d: corrupting byte %d (%d->%d)\n",
163                         i, loc, buf[loc], tmp[loc]);
164
165                 check(0, tmp, size, allow_consume);
166         }
167 }
168
169 static void
170 partial_read(uint8_t *buf, size_t size) {
171         T_t t, *tp;
172         asn_dec_rval_t rval;
173         uint8_t tbuf1[size];
174         uint8_t tbuf2[size];
175         uint8_t tbuf3[size];
176
177         fprintf(stderr, "\nPartial read sequence...\n");
178
179         /*
180          * Divide the space (size) into three blocks in various combinations:
181          *   |<----->i1<----->i2<----->|
182          *   ^ buf                     ^ buf+size
183          * Try to read block by block.
184          */
185         for(size_t i1 = 0; i1 < size; i1++) {
186                 for(size_t i2 = i1; i2 < size; i2++) {
187                         uint8_t *chunk1 = buf;
188                         size_t size1 = i1;
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;
193
194                         fprintf(stderr, "\n%d:{%d, %d, %d}...\n",
195                                 (int)size, (int)size1, (int)size2, (int)size3);
196
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);
203
204                         tp = memset(&t, 0, sizeof(t));
205
206                         fprintf(stderr, "=> Chunk 1 (%d):\n", (int)size1);
207                         rval = ber_decode(0, &asn_DEF_T, (void **)&tp,
208                                 tbuf1, size1);
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);
215                                 size2 += leftover;
216                         }
217
218                         fprintf(stderr, "=> Chunk 2 (%d):\n", (int)size2);
219                         rval = ber_decode(0, &asn_DEF_T, (void **)&tp,
220                                 tbuf2, size2);
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);
227                                 size3 += leftover;
228                         }
229
230                         fprintf(stderr, "=> Chunk 3 (%d):\n", (int)size3);
231                         rval = ber_decode(0, &asn_DEF_T, (void **)&tp,
232                                 tbuf3, size3);
233                         assert(rval.code == RC_OK);
234                         assert(rval.consumed == size3);
235
236                         ASN_STRUCT_RESET(asn_DEF_T, &t);
237                 }
238         }
239 }
240
241 int
242 main(int ac, char **av) {
243
244         (void)ac;       /* Unused argument */
245         (void)av;       /* Unused argument */
246
247         /* Check that the full buffer may be decoded normally */
248         check(1, buf1, sizeof(buf1), sizeof(buf1) - 3);
249
250         /* Check that some types of buffer corruptions will lead to failure */
251         try_corrupt(buf1, sizeof(buf1) - 3, sizeof(buf1) - 3);
252
253         /* Split the buffer in parts and check decoder restartability */
254         partial_read(buf1, sizeof(buf1) - 3);
255
256         return 0;
257 }