blob: c6b55fd05c270f5e95daad308916f2e9ae3ed187 [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");
Lev Walkin84b57882016-03-13 16:55:28 -0700130 system("pwd");
131 system("env");
Lev Walkinc6b34cc2016-03-13 23:46:09 -0700132 system("cd .. && find .");
Lev Walkinf15320b2004-06-03 03:38:44 +0000133 exit(EX_NOINPUT);
134 }
135
136 if(failed)
137 exit(EX_DATAERR);
138 return 0;
139}
140
141static int
142check(const char *fname,
143 enum asn1p_flags parser_flags,
144 enum asn1f_flags fixer_flags) {
145 asn1p_t *asn;
146 int expected_parseable; /* Is it expected to be parseable? */
147 int expected_fix_code; /* What code a fixer must return */
148 int r_value = 0;
149
150 /*
151 * Figure out how the processing should go by inferring
152 * expectations from the file name.
153 */
154 if(strstr(fname, "-OK.")) {
155 expected_parseable = 1;
156 expected_fix_code = 0;
157 } else if(strstr(fname, "-NP.")) {
158 expected_parseable = 0;
159 expected_fix_code = 123; /* Does not matter */
160 } else if(strstr(fname, "-SE.")) {
161 expected_parseable = 1;
162 expected_fix_code = -1; /* Semantically incorrect */
163 } else if(strstr(fname, "-SW.")) {
164 expected_parseable = 1;
165 expected_fix_code = 1; /* Semantically suspicious */
166 } else {
167 fprintf(stderr, "%s: Invalid file name format\n", fname);
168 return -1;
169 }
170
Lev Walkin4b553412005-08-14 14:45:44 +0000171 /* Flag modifiers */
172 if(strstr(fname, "-blessSize-"))
173 fixer_flags |= A1F_EXTENDED_SizeConstraint;
174
Lev Walkinf15320b2004-06-03 03:38:44 +0000175 fprintf(stderr, "[=> %s]\n", fname);
176
177 /*
178 * Perform low-level parsing.
179 */
180 if(!expected_parseable)
181 fprintf(stderr, "Expecting error...\n");
182 asn = asn1p_parse_file(fname, parser_flags);
183 if(asn == NULL) {
184 if(expected_parseable) {
185 fprintf(stderr, "Cannot parse file \"%s\"\n", fname);
186 r_value = -1;
187 } else {
188 fprintf(stderr,
189 "Previous error is EXPECTED, no worry\n");
190 }
191 } else if(!expected_parseable) {
192 fprintf(stderr,
193 "The file \"%s\" is not expected to be parseable, "
194 "yet parsing was successfull!\n", fname);
195 r_value = -1;
196 }
Lev Walkin6b3ff542006-03-06 14:51:00 +0000197 if(!asn) return r_value;
198
199 if(r_value == 0) {
200 asn1p_t *std_asn;
Lev Walkina57f2822016-01-24 18:19:35 -0800201 std_asn = asn1p_parse_file("../skeletons/standard-modules/ASN1C-UsefulInformationObjectClasses.asn1", A1P_NOFLAGS);
Lev Walkin6b3ff542006-03-06 14:51:00 +0000202 if(std_asn) {
203 asn1p_module_t *mod;
Lev Walkin9c2285a2006-03-09 08:49:26 +0000204 while((mod = TQ_REMOVE(&(std_asn->modules), mod_next))) {
205 mod->_tags |= MT_STANDARD_MODULE;
Lev Walkin6b3ff542006-03-06 14:51:00 +0000206 TQ_ADD(&(asn->modules), mod, mod_next);
Lev Walkin9c2285a2006-03-09 08:49:26 +0000207 }
Lev Walkin223000a2006-09-13 00:21:58 +0000208 asn1p_delete(std_asn);
Lev Walkin6b3ff542006-03-06 14:51:00 +0000209 }
210 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000211
212 /*
213 * Perform semantical checks and fixes.
214 */
Lev Walkin6b3ff542006-03-06 14:51:00 +0000215 if(r_value == 0) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000216 int ret;
217
218 if(expected_fix_code)
219 fprintf(stderr, "Expecting some problems...\n");
220
221 ret = asn1f_process(asn, fixer_flags, 0);
222 if(ret) {
223 if(ret == expected_fix_code) {
224 fprintf(stderr,
225 "Previous error is EXPECTED, "
226 "no worry\n");
227 } else {
228 fprintf(stderr,
229 "Cannot process file \"%s\": %d\n",
230 fname, ret);
231 r_value = -1;
232 }
233 } else if(ret != expected_fix_code) {
234 fprintf(stderr,
235 "File \"%s\" is expected "
236 "to be semantically incorrect, "
237 "yet processing was successful!\n",
238 fname);
239 r_value = -1;
240 }
241 }
242
243 /*
244 * Check validity of some values, if grammar has special
245 * instructions for that.
246 */
Lev Walkin6b3ff542006-03-06 14:51:00 +0000247 if(r_value == 0) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000248 if(post_fix_check(asn))
249 r_value = -1;
250 }
251
252 /*
Lev Walkin6b3ff542006-03-06 14:51:00 +0000253 * Destroy the asn.
Lev Walkinf15320b2004-06-03 03:38:44 +0000254 */
Lev Walkin55f106a2006-09-15 16:34:12 +0000255#ifdef CLEAN_EVERYTHING
Lev Walkin223000a2006-09-13 00:21:58 +0000256 asn1p_delete(asn);
Lev Walkin55f106a2006-09-15 16:34:12 +0000257#endif
Lev Walkinf15320b2004-06-03 03:38:44 +0000258
259 return r_value;
260}
261
262
263static int
264post_fix_check(asn1p_t *asn) {
265 asn1p_module_t *mod;
266 asn1p_expr_t *expr;
267 int r_value = 0;
268
269 TQ_FOR(mod, &(asn->modules), mod_next) {
270 TQ_FOR(expr, &(mod->members), next) {
271 assert(expr->Identifier);
272 if(strncmp(expr->Identifier, "check-", 6) == 0) {
273 if(post_fix_check_element(mod, expr))
274 r_value = -1;
275 }
276 }
277 }
278
279 return r_value;
280}
281
282
283static int
284post_fix_check_element(asn1p_module_t *mod, asn1p_expr_t *check_expr) {
285 asn1p_expr_t *expr = NULL;
286 char *name;
287 asn1p_value_t *value;
288
289 if(check_expr->expr_type != ASN_BASIC_INTEGER
290 || check_expr->meta_type != AMT_VALUE) {
291 fprintf(stderr,
292 "CHECKER: Unsupported type of \"%s\" value: "
293 "%d at line %d of %s\n",
294 check_expr->Identifier,
295 check_expr->expr_type,
296 check_expr->_lineno,
297 mod->source_file_name
298 );
299 return -1;
300 }
301
302 assert(check_expr->meta_type == AMT_VALUE);
303
304 value = check_expr->value;
305 if(value == NULL || value->type != ATV_INTEGER) {
306 fprintf(stderr,
307 "CHECKER: Unsupported value type of \"%s\": "
308 "%d at line %d of %s\n",
309 check_expr->Identifier,
Lev Walkin409c44e2004-06-05 08:57:10 +0000310 value?(signed)value->type:-1,
Lev Walkinf15320b2004-06-03 03:38:44 +0000311 expr->_lineno,
312 mod->source_file_name
313 );
314 return -1;
315 }
316
317 name = check_expr->Identifier + sizeof("check-") - 1;
318
319 /*
320 * Scan in search for the original.
321 */
322 TQ_FOR(expr, &(mod->members), next) {
323 if(strcmp(expr->Identifier, name) == 0)
324 break;
325 }
326
327 if(expr == NULL) {
328 fprintf(stderr,
329 "CHECKER: Value \"%s\" requested by "
330 "\"check-%s\" at line %d of %s is not found!\n",
331 name, name, check_expr->_lineno,
332 mod->source_file_name
333 );
334 return -1;
335 }
336
337 if(0 && expr->expr_type != check_expr->expr_type) {
338 fprintf(stderr,
339 "CHECKER: Value type of \"%s\" (=%d) at line %d "
340 "does not have desired type %d as requested by "
341 "\"check-%s\" in %s\n",
342 expr->Identifier,
343 expr->expr_type,
344 expr->_lineno,
345 check_expr->expr_type,
346 name,
347 mod->source_file_name
348 );
349 return -1;
350 }
351
352 if(expr->value == NULL
353 || expr->value->type != value->type) {
354 fprintf(stderr,
355 "CHECKER: Value of \"%s\" (\"%s\", type=%d) at line %d "
356 "does not have desired type %d as requested by "
357 "\"check-%s\" in %s\n",
358 expr->Identifier,
359 asn1f_printable_value(expr->value),
360 expr->value->type,
361 expr->_lineno,
362 value->type,
363 name,
364 mod->source_file_name
365 );
366 return -1;
367 }
368
369 assert(value->type = ATV_INTEGER);
370
371 return 0;
372}
373
374