blob: 2a09616c1862a5699eb19d8b2e93c64e692a25f5 [file] [log] [blame]
Lev Walkin1e609cf2004-09-27 20:50:48 +00001#undef NDEBUG
2#include <stdio.h>
3#include <stdlib.h>
4#include <sys/types.h>
Lev Walkine0d321a2014-09-11 01:28:57 -07005#include <unistd.h> /* for chdir(2), getcwd(3) */
Lev Walkin1e609cf2004-09-27 20:50:48 +00006#include <string.h>
7#include <dirent.h>
8#include <assert.h>
9#include <errno.h>
10
11#include <T.h>
12
Lev Walkine0d321a2014-09-11 01:28:57 -070013#ifndef SRCDIR
14#define SRCDIR_S ".."
15#else
16#define STRINGIFY_MACRO2(x) #x
17#define STRINGIFY_MACRO(x) STRINGIFY_MACRO2(x)
18#define SRCDIR_S STRINGIFY_MACRO(SRCDIR)
19#endif
20
Lev Walkin1e609cf2004-09-27 20:50:48 +000021enum expectation {
22 EXP_OK, /* Encoding/decoding must succeed */
23 EXP_BROKEN, /* Decoding must fail */
24 EXP_RECLESS, /* Reconstruction is allowed to yield less data */
Lev Walkinc5364602004-10-05 06:38:38 +000025 EXP_DIFFERENT, /* Reconstruction will yield different encoding */
Lev Walkin1e609cf2004-09-27 20:50:48 +000026};
27
28static unsigned char buf[4096];
29static int buf_offset;
30
31static int
32_buf_writer(const void *buffer, size_t size, void *app_key) {
33 unsigned char *b, *bend;
34 (void)app_key;
35 assert(buf_offset + size < sizeof(buf));
Vasil Velichkovedd82a92017-10-10 03:15:32 +030036 if (buffer) {
37 memcpy(buf + buf_offset, buffer, size);
38 }
Lev Walkin1e609cf2004-09-27 20:50:48 +000039 b = buf + buf_offset;
40 bend = b + size;
41 printf("=> [");
42 for(; b < bend; b++)
43 printf(" %02X", *b);
Lev Walkin1715b322013-03-28 04:02:13 -070044 printf("]:%zd\n", size);
Lev Walkin1e609cf2004-09-27 20:50:48 +000045 buf_offset += size;
46 return 0;
47}
48
49static int
50save_object(T_t *st) {
51 asn_enc_rval_t rval; /* Return value */
52
53 buf_offset = 0;
54
Lev Walkinc7400c52004-09-29 13:14:36 +000055 rval = der_encode(&asn_DEF_T, st, _buf_writer, 0);
Lev Walkin1e609cf2004-09-27 20:50:48 +000056 if (rval.encoded == -1) {
57 fprintf(stderr,
58 "Cannot encode %s: %s\n",
59 rval.failed_type->name, strerror(errno));
60 assert(rval.encoded != -1);
61 return -1; /* JIC */
62 }
63
64 fprintf(stderr, "SAVED OBJECT IN SIZE %d\n", buf_offset);
65
66 return 0;
67}
68
69static T_t *
Lev Walkin5b63acf2014-01-14 01:48:37 -080070load_object(enum expectation expectation, unsigned char *fbuf, size_t size) {
Lev Walkin90bf7ae2004-10-20 15:46:56 +000071 asn_dec_rval_t rval;
Lev Walkin1e609cf2004-09-27 20:50:48 +000072 T_t *st = 0;
73 int csize;
74
Lev Walkin5b63acf2014-01-14 01:48:37 -080075 fprintf(stderr, "LOADING OBJECT OF SIZE %d\n", (int)size);
Lev Walkin1e609cf2004-09-27 20:50:48 +000076
77 /* Perform multiple iterations with multiple chunks sizes */
78 for(csize = 1; csize < 20; csize += 1) {
79 int fbuf_offset = 0;
80 int fbuf_left = size;
81 int fbuf_chunk = csize;
82
Bi-Ruei, Chiu1f87ac02017-08-20 01:25:45 +080083 if(st) ASN_STRUCT_FREE(asn_DEF_T, st);
Lev Walkin1e609cf2004-09-27 20:50:48 +000084 st = 0;
85
86 do {
87 fprintf(stderr, "Decoding from %d with %d (left %d)\n",
88 fbuf_offset, fbuf_chunk, fbuf_left);
Lev Walkinc7400c52004-09-29 13:14:36 +000089 rval = ber_decode(0, &asn_DEF_T, (void **)&st,
Lev Walkin1e609cf2004-09-27 20:50:48 +000090 fbuf + fbuf_offset,
91 fbuf_chunk < fbuf_left
92 ? fbuf_chunk : fbuf_left);
93 fbuf_offset += rval.consumed;
94 fbuf_left -= rval.consumed;
95 if(rval.code == RC_WMORE)
96 fbuf_chunk += 1; /* Give little more */
97 else
98 fbuf_chunk = csize; /* Back off */
99 } while(fbuf_left && rval.code == RC_WMORE);
100
101 if(expectation != EXP_BROKEN) {
102 assert(rval.code == RC_OK);
Lev Walkin5b63acf2014-01-14 01:48:37 -0800103 assert(fbuf_offset == (ssize_t)size);
Lev Walkin1e609cf2004-09-27 20:50:48 +0000104 } else {
105 assert(rval.code != RC_OK);
106 fprintf(stderr, "Failed, but this was expected\n");
Bi-Ruei, Chiu1f87ac02017-08-20 01:25:45 +0800107 ASN_STRUCT_FREE(asn_DEF_T, st);
Lev Walkin1e609cf2004-09-27 20:50:48 +0000108 st = 0; /* ignore leak for now */
109 }
110 }
111
Lev Walkinc7400c52004-09-29 13:14:36 +0000112 if(st) asn_fprint(stderr, &asn_DEF_T, st);
Lev Walkin1e609cf2004-09-27 20:50:48 +0000113 return st;
114}
115
116
117static void
Lev Walkin5b63acf2014-01-14 01:48:37 -0800118process_data(enum expectation expectation, unsigned char *fbuf, ssize_t size) {
Lev Walkin1e609cf2004-09-27 20:50:48 +0000119 T_t *st;
120 int ret;
121
122 st = load_object(expectation, fbuf, size);
123 if(!st) return;
124
125 ret = save_object(st);
Lev Walkin5b63acf2014-01-14 01:48:37 -0800126 assert(buf_offset < (ssize_t)sizeof(buf));
Lev Walkin1e609cf2004-09-27 20:50:48 +0000127 assert(ret == 0);
128
Lev Walkinc5364602004-10-05 06:38:38 +0000129 switch(expectation) {
130 case EXP_RECLESS:
Lev Walkin1e609cf2004-09-27 20:50:48 +0000131 assert(buf_offset > 0 && buf_offset < size);
132 assert(memcmp(buf + 2, fbuf + 2, buf_offset - 2) == 0);
Lev Walkinc5364602004-10-05 06:38:38 +0000133 break;
134 case EXP_DIFFERENT:
135 assert(buf_offset > 0 && buf_offset < size);
136 break;
137 case EXP_BROKEN:
Lev Walkinb5ce57f2005-02-18 09:41:13 +0000138 assert(buf_offset != size
139 || memcmp(buf, fbuf, buf_offset));
Lev Walkinc5364602004-10-05 06:38:38 +0000140 break;
Lev Walkin1c830032004-10-28 13:24:27 +0000141 case EXP_OK:
Lev Walkin5b63acf2014-01-14 01:48:37 -0800142 assert(buf_offset == (ssize_t)size);
Lev Walkinb5ce57f2005-02-18 09:41:13 +0000143 assert(memcmp(buf, fbuf, buf_offset) == 0);
Lev Walkin1c830032004-10-28 13:24:27 +0000144 break;
Lev Walkin1e609cf2004-09-27 20:50:48 +0000145 }
146
Bi-Ruei, Chiu1f87ac02017-08-20 01:25:45 +0800147 ASN_STRUCT_FREE(asn_DEF_T, st);
Lev Walkin1e609cf2004-09-27 20:50:48 +0000148}
149
150/*
151 * Decode the .der files and try to regenerate them.
152 */
153static int
154process(const char *fname) {
Lev Walkine0d321a2014-09-11 01:28:57 -0700155 char prevdir[256];
Lev Walkin5b63acf2014-01-14 01:48:37 -0800156 unsigned char fbuf[4096];
Lev Walkin1e609cf2004-09-27 20:50:48 +0000157 char *ext = strrchr(fname, '.');
158 enum expectation expectation;
Lev Walkin435469e2017-10-19 03:39:23 -0700159 char *cwd;
Lev Walkin1e609cf2004-09-27 20:50:48 +0000160 int ret;
161 int rd;
162 FILE *fp;
163
164 if(ext == 0 || strcmp(ext, ".ber"))
165 return 0;
166
167 switch(ext[-1]) {
168 case 'B': /* The file is intentionally broken */
169 expectation = EXP_BROKEN; break;
Lev Walkinc5364602004-10-05 06:38:38 +0000170 case 'D': /* Reconstructing should yield different data */
171 expectation = EXP_DIFFERENT; break;
Lev Walkin1e609cf2004-09-27 20:50:48 +0000172 case 'L': /* Extensions are present */
173 expectation = EXP_RECLESS; break;
174 default:
175 expectation = EXP_OK; break;
176 }
177
178 fprintf(stderr, "\nProcessing file [../%s]\n", fname);
179
Lev Walkin435469e2017-10-19 03:39:23 -0700180 cwd = getcwd(prevdir, sizeof(prevdir));
181 assert(cwd != NULL);
Lev Walkine0d321a2014-09-11 01:28:57 -0700182 ret = chdir(SRCDIR_S "/data-62");
Lev Walkin1e609cf2004-09-27 20:50:48 +0000183 assert(ret == 0);
184 fp = fopen(fname, "r");
Lev Walkine0d321a2014-09-11 01:28:57 -0700185 ret = chdir(prevdir);
Lev Walkin1e609cf2004-09-27 20:50:48 +0000186 assert(ret == 0);
187 assert(fp);
188
189 rd = fread(fbuf, 1, sizeof(fbuf), fp);
190 fclose(fp);
191
Lev Walkin5b63acf2014-01-14 01:48:37 -0800192 assert(rd < (ssize_t)sizeof(fbuf)); /* expect small files */
Lev Walkin1e609cf2004-09-27 20:50:48 +0000193
194 process_data(expectation, fbuf, rd);
195
196 return 1;
197}
198
199int
200main() {
201 DIR *dir;
202 struct dirent *dent;
203 int processed_files = 0;
Lev Walkinc5364602004-10-05 06:38:38 +0000204 char *str;
Lev Walkin1e609cf2004-09-27 20:50:48 +0000205
Lev Walkine0d321a2014-09-11 01:28:57 -0700206 dir = opendir(SRCDIR_S "/data-62");
Lev Walkin1e609cf2004-09-27 20:50:48 +0000207 assert(dir);
208
Lev Walkinc5364602004-10-05 06:38:38 +0000209 str = getenv("DATA_62_FILE");
210 if(str && strncmp(str, "data-62-", 8) == 0)
211 process(str);
Lev Walkin1e609cf2004-09-27 20:50:48 +0000212
Lev Walkinc5364602004-10-05 06:38:38 +0000213 while((dent = readdir(dir))) {
214 if(strncmp(dent->d_name, "data-62-", 8) == 0)
215 if(process(dent->d_name))
216 processed_files++;
Lev Walkin1e609cf2004-09-27 20:50:48 +0000217 }
218
219 assert(processed_files);
220 closedir(dir);
221
222 return 0;
223}
224