1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <errno.h>
5 #include <assert.h>
6 
7 #include "asn1parser.h"
8 
9 static asn1p_expr_t *asn1p_expr_clone_impl(asn1p_expr_t *expr, int skip_extensions, asn1p_expr_t *(*)(asn1p_expr_t *, void *), void *);
10 static asn1p_value_t *value_resolver(asn1p_value_t *, void *arg);
11 
12 /*
13  * Construct a new empty types collection.
14  */
15 asn1p_expr_t *
asn1p_expr_new(int _lineno,asn1p_module_t * mod)16 asn1p_expr_new(int _lineno, asn1p_module_t *mod) {
17 	asn1p_expr_t *expr;
18 
19 	expr = calloc(1, sizeof *expr);
20 	if(expr) {
21 		TQ_INIT(&(expr->members));
22 		expr->spec_index = -1;
23 		expr->module = mod;
24 		expr->_lineno = _lineno;
25 	}
26 
27 	return expr;
28 }
29 
30 asn1p_expr_t *
asn1p_expr_clone(asn1p_expr_t * expr,int skip_extensions)31 asn1p_expr_clone(asn1p_expr_t *expr, int skip_extensions) {
32 	return asn1p_expr_clone_impl(expr, skip_extensions, 0, 0);
33 }
34 
35 asn1p_expr_t *
asn1p_expr_clone_with_resolver(asn1p_expr_t * expr,asn1p_expr_t * (* r)(asn1p_expr_t *,void *),void * rarg)36 asn1p_expr_clone_with_resolver(asn1p_expr_t *expr, asn1p_expr_t *(*r)(asn1p_expr_t *, void *), void *rarg) {
37 	return asn1p_expr_clone_impl(expr, 0, r, rarg);
38 }
39 
40 static asn1p_expr_t *
asn1p_expr_clone_impl(asn1p_expr_t * expr,int skip_extensions,asn1p_expr_t * (* r)(asn1p_expr_t *,void *),void * rarg)41 asn1p_expr_clone_impl(asn1p_expr_t *expr, int skip_extensions, asn1p_expr_t *(*r)(asn1p_expr_t *, void *), void *rarg) {
42 	asn1p_value_t *(*vr)(asn1p_value_t *, void *) = 0;
43 	asn1p_expr_t *clone = 0;
44 	asn1p_expr_t *tcmemb;	/* Child of tc */
45 	int hit_ext = 0;
46 
47 #define	CLCOPY(field)	do { clone->field = expr->field; } while(0)
48 #define	CLCLONE(field, func)	do { if(expr->field) {			\
49 			clone->field = func(expr->field);		\
50 			if(clone->field == NULL) {			\
51 				asn1p_expr_free(clone);			\
52 				return NULL;				\
53 			}						\
54 		} } while(0)
55 #define	CLVRCLONE(field, func)	do { if(expr->field) {			\
56 			clone->field = func(expr->field, vr, rarg);	\
57 			if(clone->field == NULL) {			\
58 				asn1p_expr_free(clone);			\
59 				return NULL;				\
60 			}						\
61 		} } while(0)
62 
63 	if(r) {
64 		vr = value_resolver;
65 		clone = r(expr, rarg);
66 		if(clone) {
67 			/* Merge constraints */
68 			if(expr->constraints) {
69 				asn1p_constraint_t *tmpct = asn1p_constraint_clone_with_resolver(expr->constraints, vr, rarg);
70 				if(clone->constraints) {
71 					if(asn1p_constraint_insert(clone->constraints, tmpct)) {
72 						asn1p_constraint_free(tmpct);
73 						asn1p_expr_free(clone);
74 						return NULL;
75 					}
76 				} else {
77 					clone->constraints = tmpct;
78 				}
79 				assert(expr->combined_constraints == 0);
80 			}
81 			/* Merge defaults */
82 			CLCOPY(marker.flags);
83 			CLVRCLONE(marker.default_value,
84 				asn1p_value_clone_with_resolver);
85 			if(clone->tag.tag_class == TC_NOCLASS) {
86 				CLCOPY(tag);
87 			} else if(expr->tag.tag_class != TC_NOCLASS) {
88 				fprintf(stderr, "asn1c does not support "
89 					"nested tagging in parameterization, "
90 					"necessary at line %d\n",
91 					expr->_lineno);
92 				asn1p_expr_free(clone);
93 				return NULL;
94 			}
95 			return clone;
96 		} else if(errno != ESRCH) {
97 			return NULL;	/* Hard error */
98 		}
99 	}
100 	if(!clone) clone = asn1p_expr_new(expr->_lineno, expr->module);
101 	if(!clone) return NULL;
102 
103 	/*
104 	 * Copy simple fields.
105 	 */
106 	CLCOPY(meta_type);
107 	CLCOPY(expr_type);
108 	CLCOPY(tag);
109 	CLCOPY(marker.flags);		/* OPTIONAL/DEFAULT */
110 	CLCOPY(_mark);
111 
112 	clone->data = 0;	/* Do not clone this */
113 	clone->data_free = 0;	/* Do not clone this */
114 
115 	/*
116 	 * Clone complex fields.
117 	 */
118 	CLCLONE(Identifier, strdup);
119 	CLCLONE(reference, asn1p_ref_clone);
120 	CLVRCLONE(constraints, asn1p_constraint_clone_with_resolver);
121 	CLVRCLONE(combined_constraints, asn1p_constraint_clone_with_resolver);
122 	CLCLONE(lhs_params, asn1p_paramlist_clone);
123 	CLVRCLONE(value, asn1p_value_clone_with_resolver);
124 	CLVRCLONE(marker.default_value, asn1p_value_clone_with_resolver);
125 	CLCLONE(with_syntax, asn1p_wsyntx_clone);
126 
127 	/*
128 	 * Copy all the children of this expr.
129 	 */
130 	TQ_FOR(tcmemb, &(expr->members), next) {
131 		asn1p_expr_t *cmemb;
132 
133 		if(skip_extensions
134 		&& tcmemb->expr_type == A1TC_EXTENSIBLE) {
135 			hit_ext++; /* Even if hit_ext wraps around, we're OK. */
136 			continue;
137 		}
138 		if(hit_ext == 1) continue;	/* Skip between ...'s */
139 
140 		cmemb = asn1p_expr_clone_impl(tcmemb, skip_extensions, r, rarg);
141 		if(cmemb == NULL) {
142 			asn1p_expr_free(clone);
143 			return NULL;
144 		}
145 		asn1p_expr_add(clone, cmemb);
146 	}
147 
148 	return clone;
149 }
150 
151 
152 static asn1p_value_t *
value_resolver(asn1p_value_t * value,void * rarg)153 value_resolver(asn1p_value_t *value, void *rarg) {
154 	asn1p_value_t *cval;
155 	asn1p_expr_t *tmpexpr;
156 	asn1p_expr_t *target;
157 	asn1p_ref_t *ref;
158 	struct {
159 		asn1p_expr_t *(*expr_resolve)(asn1p_expr_t *, void *arg);
160 	} *varg = rarg;
161 
162 	if(!value || value->type != ATV_REFERENCED) {
163 		errno = ESRCH;
164 		return NULL;
165 	}
166 
167 	ref = value->value.reference;
168 	tmpexpr = asn1p_expr_new(ref->_lineno, 0);
169 	tmpexpr->meta_type = AMT_TYPEREF;
170 	tmpexpr->expr_type = A1TC_REFERENCE;
171 	tmpexpr->reference = ref;
172 	target = varg->expr_resolve(tmpexpr, rarg);
173 	tmpexpr->reference = 0;
174 	asn1p_expr_free(tmpexpr);
175 
176 	if(!target)
177 		return NULL;	/* errno's are compatible */
178 
179 	if(target->meta_type == AMT_VALUE) {
180 		if(!target->value) {
181 			fprintf(stderr,
182 			"FATAL: Parameterization did not resolve "
183 			"value reference at line %d\n", ref->_lineno);
184 			asn1p_expr_free(target);
185 			errno = EPERM;
186 			return NULL;
187 		}
188 		cval = asn1p_value_clone(target->value);
189 	} else if(target->meta_type == AMT_VALUESET) {
190 		if(!target->constraints) {
191 			fprintf(stderr,
192 			"FATAL: Parameterization did not resolve "
193 			"value set reference at line %d\n", ref->_lineno);
194 			asn1p_expr_free(target);
195 			errno = EPERM;
196 			return NULL;
197 		}
198 		cval = asn1p_value_fromconstr(target->constraints, 1);
199 	} else {
200 		errno = EPERM;
201 		cval = NULL;
202 	}
203 
204 	asn1p_expr_free(target);
205 	return cval;
206 }
207 
208 /*
209  * Add expression as a member of another.
210  */
211 void
asn1p_expr_add(asn1p_expr_t * to,asn1p_expr_t * what)212 asn1p_expr_add(asn1p_expr_t *to, asn1p_expr_t *what) {
213 	TQ_ADD(&(to->members), what, next);
214 	what->parent_expr = to;
215 }
216 
217 /*
218  * Add inner expressions as members of another.
219  */
220 void
asn1p_expr_add_many(asn1p_expr_t * to,asn1p_expr_t * from_what)221 asn1p_expr_add_many(asn1p_expr_t *to, asn1p_expr_t *from_what) {
222 	asn1p_expr_t *expr;
223 	TQ_FOR(expr, &(from_what->members), next) {
224         expr->parent_expr = to;
225     }
226 	TQ_CONCAT(&(to->members), &(from_what->members), next);
227 }
228 
229 
230 /*
231  * Destruct the types collection structure.
232  */
233 void
asn1p_expr_free(asn1p_expr_t * expr)234 asn1p_expr_free(asn1p_expr_t *expr) {
235 	if(expr) {
236 		asn1p_expr_t *tm;
237 
238 		/* Remove all children */
239 		while((tm = TQ_REMOVE(&(expr->members), next))) {
240 			if(tm->parent_expr != expr)
241 				printf("<%s:%p !-> %s:%p>\n",
242 					tm->Identifier, tm->parent_expr,
243 					expr->Identifier, expr);
244 			assert(tm->parent_expr == expr);
245 			asn1p_expr_free(tm);
246 		}
247 
248 		if(expr->Identifier)
249 			free(expr->Identifier);
250 		if(expr->reference)
251 			asn1p_ref_free(expr->reference);
252 		if(expr->constraints)
253 			asn1p_constraint_free(expr->constraints);
254 		if(expr->combined_constraints)
255 			asn1p_constraint_free(expr->combined_constraints);
256 		if(expr->lhs_params)
257 			asn1p_paramlist_free(expr->lhs_params);
258 		if(expr->value)
259 			asn1p_value_free(expr->value);
260 		if(expr->marker.default_value)
261 			asn1p_value_free(expr->marker.default_value);
262 		if(expr->with_syntax)
263 			asn1p_wsyntx_free(expr->with_syntax);
264 
265 		if(expr->data && expr->data_free)
266 			expr->data_free(expr->data);
267 
268 		memset(expr, 0, sizeof(*expr));
269 		free(expr);
270 	}
271 }
272 
273 
asn1p_tag2string(struct asn1p_type_tag_s * tag,char * buf)274 char *asn1p_tag2string(struct asn1p_type_tag_s *tag, char *buf) {
275 	static char buf_stat[TAG2STRING_BUFFER_SIZE];
276 	char *start;
277 	char *end;
278 
279 	if(!buf) buf = buf_stat;
280 	start = buf;
281 	end = buf + TAG2STRING_BUFFER_SIZE;
282 
283 	if(tag->tag_class == TC_NOCLASS) {
284 		*buf = 0;
285 		return buf;
286 	}
287 
288 	strcpy(buf, "[");
289 	switch(tag->tag_class) {
290 	case TC_NOCLASS:
291 		assert(tag->tag_class != TC_NOCLASS);
292 		break;
293 	case TC_UNIVERSAL:	strcat(buf, "UNIVERSAL ");	break;
294 	case TC_PRIVATE:	strcat(buf, "PRIVATE ");	break;
295 	case TC_APPLICATION:	strcat(buf, "APPLICATION ");	break;
296 	case TC_CONTEXT_SPECIFIC:
297 		break;
298 	}
299 	buf += snprintf(buf + strlen(buf), end - buf,
300 		"%" PRIdASN "]", tag->tag_value);
301 	assert((unsigned int)(buf - end) > sizeof(" IMPLICIT "));
302 
303 	switch(tag->tag_mode) {
304 	case TM_DEFAULT: break;
305 	case TM_IMPLICIT: strcat(buf, " IMPLICIT"); break;
306 	case TM_EXPLICIT: strcat(buf, " EXPLICIT"); break;
307 	}
308 
309 	return start;
310 }
311