blob: 4a616e0c2786cd8d763735602728dc13d2ff5dcb [file] [log] [blame]
Lev Walkinf15320b2004-06-03 03:38:44 +00001#undef NDEBUG
Lev Walkin4efbfb72005-02-25 14:20:30 +00002#include "asn1fix_internal.h"
3
Lev Walkin93659562010-11-20 09:47:13 -08004#ifdef _WIN32
Lev Walkin4efbfb72005-02-25 14:20:30 +00005#include <io.h>
6#include <direct.h>
7#define chdir _chdir
8#else
Lev Walkinf15320b2004-06-03 03:38:44 +00009#include <dirent.h>
Lev Walkinf15320b2004-06-03 03:38:44 +000010#include <sysexits.h>
Lev Walkin4efbfb72005-02-25 14:20:30 +000011#endif
12#include <errno.h>
Lev Walkinf15320b2004-06-03 03:38:44 +000013
14#include "asn1fix.h"
Lev Walkinf15320b2004-06-03 03:38:44 +000015
Lev Walkine0d321a2014-09-11 01:28:57 -070016#ifndef TOP_SRCDIR
17#define TOP_SRCDIR_S ".."
18#else
19#define STRINGIFY_MACRO2(x) #x
20#define STRINGIFY_MACRO(x) STRINGIFY_MACRO2(x)
21#define TOP_SRCDIR_S STRINGIFY_MACRO(TOP_SRCDIR)
22#endif
23
Lev Walkinf15320b2004-06-03 03:38:44 +000024static int check(const char *fname,
25 enum asn1p_flags parser_flags,
26 enum asn1f_flags fixer_flags);
27static int post_fix_check(asn1p_t *asn);
28static int post_fix_check_element(asn1p_module_t *mod, asn1p_expr_t *expr);
29
30int
31main(int ac, char **av) {
Lev Walkin93659562010-11-20 09:47:13 -080032#ifdef _WIN32
Lev Walkin4efbfb72005-02-25 14:20:30 +000033 intptr_t dir;
34 struct _finddata_t c_file;
35#else
Lev Walkinf15320b2004-06-03 03:38:44 +000036 struct dirent *dp;
37 DIR *dir;
Lev Walkin4efbfb72005-02-25 14:20:30 +000038#endif
Lev Walkinf15320b2004-06-03 03:38:44 +000039 int failed = 0;
40 int completed = 0;
41 enum asn1p_flags parser_flags = A1P_NOFLAGS;
42 enum asn1f_flags fixer_flags = A1F_NOFLAGS;
Lev Walkin4efbfb72005-02-25 14:20:30 +000043 const char *filename;
Lev Walkin07721d52005-02-25 14:35:02 +000044 size_t len;
Lev Walkinf15320b2004-06-03 03:38:44 +000045 int ret;
46
47 /*
48 * Just in case when one decides that some flags better be
49 * enabled during `ASN1_FIXER_FLAGS=1 make check` or some
50 * similar usage.
51 */
52 if(getenv("ASN1_PARSER_FLAGS"))
53 parser_flags = atoi(getenv("ASN1_PARSER_FLAGS"));
54 if(getenv("ASN1_FIXER_FLAGS"))
55 fixer_flags = atoi(getenv("ASN1_FIXER_FLAGS"));
56
57 /*
58 * Go into a directory with tests.
59 */
60 if(ac <= 1) {
Lev Walkin08068b22016-01-24 22:49:06 -080061 const char *asn1_tests_dir = getenv("ASN1_TESTS_DIR");
62 if(!asn1_tests_dir)
63 asn1_tests_dir = TOP_SRCDIR_S "/tests";
64 fprintf(stderr, "Testing in %s...\n", asn1_tests_dir);
65 ret = chdir(asn1_tests_dir);
66 if(ret == -1)
67 fprintf(stderr, "%s: %s\n", asn1_tests_dir, strerror(errno));
68 assert(ret == 0);
Lev Walkin93659562010-11-20 09:47:13 -080069#ifdef _WIN32
Lev Walkin4efbfb72005-02-25 14:20:30 +000070 dir = _findfirst("*.asn1", &c_file);
71 assert(dir != -1L);
72#else
Lev Walkinf15320b2004-06-03 03:38:44 +000073 dir = opendir(".");
74 assert(dir);
Lev Walkin93659562010-11-20 09:47:13 -080075#endif /* _WIN32 */
Lev Walkinf15320b2004-06-03 03:38:44 +000076 } else {
77 dir = 0;
78 }
79
80 /*
81 * Scan every *.asn1 file and try to parse and fix it.
82 */
83 if(dir) {
Lev Walkin93659562010-11-20 09:47:13 -080084#ifdef _WIN32
Lev Walkin4efbfb72005-02-25 14:20:30 +000085 do {
86 filename = c_file.name;
87#else
Lev Walkinf15320b2004-06-03 03:38:44 +000088 while((dp = readdir(dir))) {
Lev Walkin4efbfb72005-02-25 14:20:30 +000089 filename = dp->d_name;
Lev Walkin93659562010-11-20 09:47:13 -080090#endif /* _WIN32 */
Lev Walkin07721d52005-02-25 14:35:02 +000091 len = strlen(filename);
Lev Walkin4b553412005-08-14 14:45:44 +000092 if(len <= 5 || strcmp(filename + len - 5, ".asn1"))
93 continue;
94 ret = check(filename, parser_flags, fixer_flags);
95 if(ret) {
96 fprintf(stderr, "FAILED: %s\n",
97 filename);
98 failed++;
Lev Walkinf15320b2004-06-03 03:38:44 +000099 }
Lev Walkin4b553412005-08-14 14:45:44 +0000100 completed++;
Lev Walkin93659562010-11-20 09:47:13 -0800101#ifdef _WIN32
Lev Walkin4efbfb72005-02-25 14:20:30 +0000102 } while(_findnext(dir, &c_file) == 0);
103 _findclose(dir);
104#else
Lev Walkinf15320b2004-06-03 03:38:44 +0000105 }
106 closedir(dir);
Lev Walkin93659562010-11-20 09:47:13 -0800107#endif /* _WIN32 */
Lev Walkin4efbfb72005-02-25 14:20:30 +0000108
Lev Walkinf15320b2004-06-03 03:38:44 +0000109
110 fprintf(stderr,
111 "Tests COMPLETED: %d\n"
112 "Tests FAILED: %d\n"
113 ,
114 completed, failed
115 );
116 } else {
117 int i;
118 for(i = 1; i < ac; i++) {
119 ret = check(av[i], parser_flags, fixer_flags);
120 if(ret) {
121 fprintf(stderr, "FAILED: %s\n", av[i]);
122 failed++;
123 }
124 completed++;
125 }
126 }
127
128 if(completed == 0) {
129 fprintf(stderr, "No tests defined?!\n");
130 exit(EX_NOINPUT);
131 }
132
133 if(failed)
134 exit(EX_DATAERR);
135 return 0;
136}
137
138static int
139check(const char *fname,
140 enum asn1p_flags parser_flags,
141 enum asn1f_flags fixer_flags) {
142 asn1p_t *asn;
143 int expected_parseable; /* Is it expected to be parseable? */
144 int expected_fix_code; /* What code a fixer must return */
145 int r_value = 0;
146
147 /*
148 * Figure out how the processing should go by inferring
149 * expectations from the file name.
150 */
151 if(strstr(fname, "-OK.")) {
152 expected_parseable = 1;
153 expected_fix_code = 0;
154 } else if(strstr(fname, "-NP.")) {
155 expected_parseable = 0;
156 expected_fix_code = 123; /* Does not matter */
157 } else if(strstr(fname, "-SE.")) {
158 expected_parseable = 1;
159 expected_fix_code = -1; /* Semantically incorrect */
160 } else if(strstr(fname, "-SW.")) {
161 expected_parseable = 1;
162 expected_fix_code = 1; /* Semantically suspicious */
163 } else {
164 fprintf(stderr, "%s: Invalid file name format\n", fname);
165 return -1;
166 }
167
Lev Walkin4b553412005-08-14 14:45:44 +0000168 /* Flag modifiers */
169 if(strstr(fname, "-blessSize-"))
170 fixer_flags |= A1F_EXTENDED_SizeConstraint;
171
Lev Walkinf15320b2004-06-03 03:38:44 +0000172 fprintf(stderr, "[=> %s]\n", fname);
173
174 /*
175 * Perform low-level parsing.
176 */
177 if(!expected_parseable)
178 fprintf(stderr, "Expecting error...\n");
179 asn = asn1p_parse_file(fname, parser_flags);
180 if(asn == NULL) {
181 if(expected_parseable) {
182 fprintf(stderr, "Cannot parse file \"%s\"\n", fname);
183 r_value = -1;
184 } else {
185 fprintf(stderr,
186 "Previous error is EXPECTED, no worry\n");
187 }
188 } else if(!expected_parseable) {
189 fprintf(stderr,
190 "The file \"%s\" is not expected to be parseable, "
191 "yet parsing was successfull!\n", fname);
192 r_value = -1;
193 }
Lev Walkin6b3ff542006-03-06 14:51:00 +0000194 if(!asn) return r_value;
195
196 if(r_value == 0) {
197 asn1p_t *std_asn;
Lev Walkina57f2822016-01-24 18:19:35 -0800198 std_asn = asn1p_parse_file("../skeletons/standard-modules/ASN1C-UsefulInformationObjectClasses.asn1", A1P_NOFLAGS);
Lev Walkin6b3ff542006-03-06 14:51:00 +0000199 if(std_asn) {
200 asn1p_module_t *mod;
Lev Walkin9c2285a2006-03-09 08:49:26 +0000201 while((mod = TQ_REMOVE(&(std_asn->modules), mod_next))) {
202 mod->_tags |= MT_STANDARD_MODULE;
Lev Walkin6b3ff542006-03-06 14:51:00 +0000203 TQ_ADD(&(asn->modules), mod, mod_next);
Lev Walkin9c2285a2006-03-09 08:49:26 +0000204 }
Lev Walkin223000a2006-09-13 00:21:58 +0000205 asn1p_delete(std_asn);
Lev Walkin6b3ff542006-03-06 14:51:00 +0000206 }
207 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000208
209 /*
210 * Perform semantical checks and fixes.
211 */
Lev Walkin6b3ff542006-03-06 14:51:00 +0000212 if(r_value == 0) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000213 int ret;
214
215 if(expected_fix_code)
216 fprintf(stderr, "Expecting some problems...\n");
217
218 ret = asn1f_process(asn, fixer_flags, 0);
219 if(ret) {
220 if(ret == expected_fix_code) {
221 fprintf(stderr,
222 "Previous error is EXPECTED, "
223 "no worry\n");
224 } else {
225 fprintf(stderr,
226 "Cannot process file \"%s\": %d\n",
227 fname, ret);
228 r_value = -1;
229 }
230 } else if(ret != expected_fix_code) {
231 fprintf(stderr,
232 "File \"%s\" is expected "
233 "to be semantically incorrect, "
234 "yet processing was successful!\n",
235 fname);
236 r_value = -1;
237 }
238 }
239
240 /*
241 * Check validity of some values, if grammar has special
242 * instructions for that.
243 */
Lev Walkin6b3ff542006-03-06 14:51:00 +0000244 if(r_value == 0) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000245 if(post_fix_check(asn))
246 r_value = -1;
247 }
248
249 /*
Lev Walkin6b3ff542006-03-06 14:51:00 +0000250 * Destroy the asn.
Lev Walkinf15320b2004-06-03 03:38:44 +0000251 */
Lev Walkin55f106a2006-09-15 16:34:12 +0000252#ifdef CLEAN_EVERYTHING
Lev Walkin223000a2006-09-13 00:21:58 +0000253 asn1p_delete(asn);
Lev Walkin55f106a2006-09-15 16:34:12 +0000254#endif
Lev Walkinf15320b2004-06-03 03:38:44 +0000255
256 return r_value;
257}
258
259
260static int
261post_fix_check(asn1p_t *asn) {
262 asn1p_module_t *mod;
263 asn1p_expr_t *expr;
264 int r_value = 0;
265
266 TQ_FOR(mod, &(asn->modules), mod_next) {
267 TQ_FOR(expr, &(mod->members), next) {
268 assert(expr->Identifier);
269 if(strncmp(expr->Identifier, "check-", 6) == 0) {
270 if(post_fix_check_element(mod, expr))
271 r_value = -1;
272 }
273 }
274 }
275
276 return r_value;
277}
278
279
280static int
281post_fix_check_element(asn1p_module_t *mod, asn1p_expr_t *check_expr) {
282 asn1p_expr_t *expr = NULL;
283 char *name;
284 asn1p_value_t *value;
285
286 if(check_expr->expr_type != ASN_BASIC_INTEGER
287 || check_expr->meta_type != AMT_VALUE) {
288 fprintf(stderr,
289 "CHECKER: Unsupported type of \"%s\" value: "
290 "%d at line %d of %s\n",
291 check_expr->Identifier,
292 check_expr->expr_type,
293 check_expr->_lineno,
294 mod->source_file_name
295 );
296 return -1;
297 }
298
299 assert(check_expr->meta_type == AMT_VALUE);
300
301 value = check_expr->value;
302 if(value == NULL || value->type != ATV_INTEGER) {
303 fprintf(stderr,
304 "CHECKER: Unsupported value type of \"%s\": "
305 "%d at line %d of %s\n",
306 check_expr->Identifier,
Lev Walkin409c44e2004-06-05 08:57:10 +0000307 value?(signed)value->type:-1,
Lev Walkinf15320b2004-06-03 03:38:44 +0000308 expr->_lineno,
309 mod->source_file_name
310 );
311 return -1;
312 }
313
314 name = check_expr->Identifier + sizeof("check-") - 1;
315
316 /*
317 * Scan in search for the original.
318 */
319 TQ_FOR(expr, &(mod->members), next) {
320 if(strcmp(expr->Identifier, name) == 0)
321 break;
322 }
323
324 if(expr == NULL) {
325 fprintf(stderr,
326 "CHECKER: Value \"%s\" requested by "
327 "\"check-%s\" at line %d of %s is not found!\n",
328 name, name, check_expr->_lineno,
329 mod->source_file_name
330 );
331 return -1;
332 }
333
334 if(0 && expr->expr_type != check_expr->expr_type) {
335 fprintf(stderr,
336 "CHECKER: Value type of \"%s\" (=%d) at line %d "
337 "does not have desired type %d as requested by "
338 "\"check-%s\" in %s\n",
339 expr->Identifier,
340 expr->expr_type,
341 expr->_lineno,
342 check_expr->expr_type,
343 name,
344 mod->source_file_name
345 );
346 return -1;
347 }
348
349 if(expr->value == NULL
350 || expr->value->type != value->type) {
351 fprintf(stderr,
352 "CHECKER: Value of \"%s\" (\"%s\", type=%d) at line %d "
353 "does not have desired type %d as requested by "
354 "\"check-%s\" in %s\n",
355 expr->Identifier,
356 asn1f_printable_value(expr->value),
357 expr->value->type,
358 expr->_lineno,
359 value->type,
360 name,
361 mod->source_file_name
362 );
363 return -1;
364 }
365
366 assert(value->type = ATV_INTEGER);
367
368 return 0;
369}
370
371