1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <strings.h>
29 #include <unistd.h>
30 #include <fcntl.h>
31 #include <errno.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <sys/mman.h>
35 #include <synch.h>
36 
37 #if defined(DEBUG)
38 #include <stdarg.h>
39 #endif /* !DEBUG */
40 
41 #include "iconv_tm.h"
42 #include "hash.h"
43 
44 
45 /*
46  * Debug
47  */
48 #if defined(DEBUG)
49 
50 static void	trace_init(void);
51 static void	trace_message(char *, ...);
52 
53 static char	trace_option[128];
54 
55 #define	TRACE(c)		(*(trace_option + (c & 0x007f)))
56 #define	TRACE_MESSAGE(c, args)	((TRACE(c))? trace_message args: (void)0)
57 
58 #else /* !DEBUG */
59 
60 #define	trace_init()
61 #define	TRACE()
62 #define	TRACE_MESSAGE(c, args)
63 
64 #endif /* !DEBUG */
65 
66 
67 /*
68  * ITM reference information
69  */
70 typedef struct _itm_ref {
71 	char		*name;		/* ITM file name */
72 	itm_hdr_t	*hdr;		/* address of ITM */
73 	size_t		len;		/* length of ITM */
74 } itm_ref_t;
75 
76 
77 /*
78  * struct _icv_state; to keep status
79  */
80 typedef struct _icv_state {
81 	struct _itm_ref	*itm;		/* reference to ITM */
82 	itm_hdr_t	*itm_hdr;	/* address of ITM */
83 	itm_tbl_hdr_t	*direc;		/* current direction */
84 	itm_place_t	default_action;	/* default action */
85 	itm_num_t	*regs;		/* register */
86 	itm_num_t	reg_num;	/* number of register */
87 #if defined(OP_DEPTH_MAX)
88 	int		op_depth;	/* depth of operation */
89 #endif /* OP_DEPTH_MAX */
90 } icv_state_t;
91 
92 
93 /*
94  * function prototype
95  */
96 void *	_icv_open(const char *);
97 void	_icv_close(icv_state_t *);
98 size_t	_icv_iconv(icv_state_t *, const unsigned char **,
99 		    size_t *, unsigned char **, size_t *);
100 
101 static size_t	map_i_f(itm_tbl_hdr_t *,
102 			const unsigned char **, size_t *,
103 			unsigned char **, size_t *, long);
104 static size_t	map_l_f(itm_tbl_hdr_t *,
105 			const unsigned char **, size_t *,
106 			unsigned char **, size_t *, long);
107 static size_t	map_h_l(itm_tbl_hdr_t *,
108 			const unsigned char **, size_t *,
109 			unsigned char **, size_t *, long);
110 static size_t	map_d_e_l(itm_tbl_hdr_t *,
111 			const unsigned char **, size_t *,
112 			unsigned char **, size_t *, long);
113 static size_t	eval_cond_tbl(icv_state_t *, itm_place_t,
114 			const unsigned char **, size_t *,
115 			size_t, itm_direc_t *);
116 static size_t	eval_op_tbl(icv_state_t *, itm_place_t,
117 			const unsigned char **, size_t *,
118 			unsigned char **, size_t *);
119 static size_t	eval_op(icv_state_t *, itm_place2_t,
120 			const unsigned char **, size_t *,
121 			unsigned char **, size_t *);
122 
123 static itm_num_t	eval_expr(icv_state_t *, itm_place_t,
124 				size_t, const unsigned char *, size_t);
125 
126 static void		itm_ref_free(int, void *, void *, void *, size_t);
127 static itm_ref_t	*itm_ref_inc(const char *);
128 static void		itm_ref_dec(itm_ref_t *);
129 
130 static void		op_init_default(icv_state_t *);
131 static void		op_reset_default(icv_state_t *);
132 static void		regs_init(icv_state_t *);
133 
134 
135 /*
136  * macro definition
137  */
138 
139 #define	ADDR(place)	((void *)(((char *)(ist->itm_hdr)) +\
140 				((itm_place2_t)(place.itm_ptr))))
141 #define	ADDR2(place2)	((void *)(((char *)(ist->itm_hdr)) +\
142 				((itm_place2_t)(place2))))
143 #define	DADDR(n)	(((n)->size <= (sizeof ((n)->place.itm_64d))) ?	\
144 				((unsigned char *)(&((n)->place.itm_64d))) :\
145 				((unsigned char *)(ADDR((n)->place))))
146 
147 #define	REG(n)		(*(ist->regs + (n)))
148 #define	DISCARD(c)	(((*inbuf) = (void *)((*inbuf) + (c))),\
149 			((*inbytesleft) -= (c)))
150 #define	GET(c)		((c) = **inbuf, (*inbuf)++, (*inbytesleft)--)
151 #define	PUT(c)		(**outbuf = (c), (*outbuf)++, (*outbytesleft)--)
152 
153 #define	RETVALERR	((size_t)(-1))
154 #define	RETVALDIR	((size_t)(-2))
155 #define	RETVALBRK	((size_t)(-3))
156 #define	RETVALRET	((size_t)(-4))
157 
158 #define	UPDATE_ARGS()	(*inbuf = ip, \
159 			 *inbytesleft = ileft, \
160 			 *outbuf = op, \
161 			 *outbytesleft = oleft)
162 
163 /*
164  * Open; called from iconv_open()
165  */
166 void *
_icv_open(const char * itm)167 _icv_open(const char	*itm)
168 {
169 	icv_state_t	*ist;
170 	itm_hdr_t	*hdr;
171 	itm_ref_t	*itm_ref;
172 	int		r;
173 
174 	/*
175 	 * for debug
176 	 */
177 	trace_init();
178 
179 	/*
180 	 * _icv_open() primaty task
181 	 */
182 	itm_ref = itm_ref_inc(itm);
183 	if (NULL == itm_ref) {
184 		return ((void *)(-1));
185 	}
186 
187 	if (NULL == (ist = malloc(sizeof (icv_state_t)))) {
188 		r = errno;
189 		itm_ref_dec(itm_ref);
190 		errno = r;
191 		return	(NULL);
192 	}
193 
194 	ist->itm = itm_ref;
195 	ist->itm_hdr = ist->itm->hdr;
196 	ist->reg_num = ist->itm->hdr->reg_num;
197 
198 	hdr =  ist->itm->hdr;
199 	ist->direc = ADDR(hdr->direc_init_tbl);
200 	ist->default_action.itm_64d = 0;
201 #if defined(OP_DEPTH_MAX)
202 	ist->op_depth = 0;
203 #endif /* OP_DEPTH_MAX */
204 
205 
206 	/*
207 	 * brief sanity check
208 	 */
209 	if (hdr->itm_size.itm_ptr <= hdr->direc_init_tbl.itm_ptr) {
210 		_icv_close(ist);
211 		errno = ELIBBAD;
212 		return ((void *)(-1));
213 	}
214 
215 
216 	/* allocate register region */
217 	if (hdr->reg_num <= 0) {
218 		ist->regs = NULL;
219 	} else {
220 		ist->regs = malloc((sizeof (itm_num_t)) * hdr->reg_num);
221 		if (NULL == ist->regs) {
222 			r = errno;
223 			_icv_close(ist);
224 			errno = r;
225 			return ((void *)(-1));
226 		}
227 		(void) memset(ist->regs, 0,
228 		    (sizeof (itm_num_t)) * hdr->reg_num);
229 	}
230 
231 
232 	/* evaluate init operation */
233 	if (0 != ist->itm_hdr->op_init_tbl.itm_ptr) {
234 		const unsigned char	*ip = NULL;
235 		size_t			ileft = 0;
236 		unsigned char		*op = NULL;
237 		size_t			oleft = 0;
238 		(void) eval_op_tbl(ist, ist->itm_hdr->op_init_tbl, &ip,
239 		    &ileft, &op, &oleft);
240 	} else {
241 		op_init_default(ist);
242 	}
243 
244 	return	(ist);
245 }
246 
247 
248 /*
249  * Close; called from iconv_close
250  */
251 void
_icv_close(icv_state_t * ist)252 _icv_close(icv_state_t		*ist)
253 {
254 	if (NULL == ist) {
255 		errno = EBADF;
256 		return;
257 	}
258 	itm_ref_dec(ist->itm);
259 	free(ist->regs);
260 	free(ist);
261 }
262 
263 
264 /*
265  * Actual conversion; called from iconv()
266  */
267 size_t
_icv_iconv(icv_state_t * ist,const unsigned char ** inbuf,size_t * inbytesleft,unsigned char ** outbuf,size_t * outbytesleft)268 _icv_iconv(
269 	icv_state_t		*ist,
270 	const unsigned char	**inbuf,
271 	size_t			*inbytesleft,
272 	unsigned char		**outbuf,
273 	size_t			*outbytesleft)
274 {
275 	size_t			retval;
276 	itm_hdr_t		*hdr;
277 	itm_type_t		type;
278 	const unsigned char	*ip;
279 	size_t			ileft;
280 	itm_place_t		action;
281 
282 	if (NULL == ist) {
283 		errno = EBADF;
284 		TRACE_MESSAGE('e', ("_icv_iconv: error=%d\n", errno));
285 		return ((size_t)(-1));
286 	}
287 	if (NULL == inbuf) {
288 		ip = NULL;
289 		inbuf = &ip;
290 	}
291 	if (NULL == inbytesleft) {
292 		ileft = 0;
293 		inbytesleft = &ileft;
294 	}
295 
296 	hdr = ist->itm_hdr;
297 
298 	retval = 0;
299 
300 	TRACE_MESSAGE('i', ("_icv_iconv(inbuf=%p inbytesleft=%ld "
301 	    "outbuf=%p outbytesleft=%ld)\n", (NULL == inbuf) ? 0 : *inbuf,
302 	    (NULL == inbytesleft) ? 0 : *inbytesleft,
303 	    (NULL == outbuf) ? 0 : *outbuf,
304 	    (NULL == outbytesleft) ? 0 : *outbytesleft));
305 
306 	/*
307 	 * If (NULL == inbuf || NULL == *inbuf) then this conversion is
308 	 * placed into initial state.
309 	 */
310 	if ((NULL == inbuf) || (NULL == *inbuf)) {
311 		if (0 != hdr->op_reset_tbl.itm_ptr) {
312 			ist->direc = ADDR(hdr->direc_init_tbl);
313 			retval = eval_op_tbl(ist, hdr->op_reset_tbl, inbuf,
314 			    inbytesleft, outbuf, outbytesleft);
315 			if ((size_t)(-1) == retval) {
316 				return	(retval);
317 			}
318 		} else {
319 			op_reset_default(ist);
320 		}
321 		return ((size_t)(0));
322 	}
323 
324 	if (ITM_TBL_MAP_INDEX_FIXED_1_1 == ist->direc->type) {
325 		itm_map_idx_fix_hdr_t	*map_hdr;
326 		char			*map;
327 		const unsigned char	*ip;
328 		size_t			ileft;
329 		unsigned char		*op;
330 		size_t			oleft;
331 
332 		map_hdr = (itm_map_idx_fix_hdr_t *)(ist->direc + 1);
333 		map = (char *)(map_hdr + 1);
334 
335 		if (1 == map_hdr->default_error) {
336 			retval = map_i_f(ist->direc, inbuf, inbytesleft,
337 			    outbuf, outbytesleft, 0);
338 			return	(retval);
339 		}
340 
341 		ip = *inbuf;
342 		ileft = *inbytesleft;
343 		op = *outbuf;
344 		oleft = *outbytesleft;
345 
346 		while (1 <= ileft) {
347 			if (oleft < 1) {
348 				UPDATE_ARGS();
349 				errno = E2BIG;
350 				TRACE_MESSAGE('e', ("_icv_iconv: error=%d\n",
351 				    errno));
352 				return ((size_t)-1);
353 			}
354 			*(op++) = *(map + *(ip++));
355 			ileft--;
356 			oleft--;
357 
358 		}
359 		UPDATE_ARGS();
360 		return (0);
361 	} else if (ITM_TBL_MAP_INDEX_FIXED == ist->direc->type) {
362 		retval = map_i_f(ist->direc, inbuf, inbytesleft,
363 		    outbuf, outbytesleft, 0);
364 		return	(retval);
365 	} else if (ITM_TBL_MAP_HASH == ist->direc->type) {
366 		retval = map_h_l(ist->direc, inbuf, inbytesleft,
367 		    outbuf, outbytesleft, 0);
368 		return	(retval);
369 	} else if (ITM_TBL_MAP_DENSE_ENC == ist->direc->type) {
370 		retval = map_d_e_l(ist->direc, inbuf, inbytesleft,
371 		    outbuf, outbytesleft, 0);
372 		return	(retval);
373 	} else if (ITM_TBL_MAP_LOOKUP == ist->direc->type) {
374 		retval = map_l_f(ist->direc, inbuf, inbytesleft,
375 		    outbuf, outbytesleft, 0);
376 		return	(retval);
377 	}
378 
379 #if defined(OP_DEPTH_MAX)
380 	ist->op_depth = 0;
381 #endif /* OP_DEPTH_MAX */
382 
383 
384 	/*
385 	 * Main loop; basically 1 loop per 1 output character
386 	 */
387 retry_cond_eval:
388 	while (0 < *inbytesleft) {
389 		itm_tbl_hdr_t	*direc_hdr;
390 		itm_direc_t	*direc;
391 		long		i;
392 
393 		direc_hdr = ist->direc;
394 		direc = (itm_direc_t *)(ist->direc + 1);
395 		for (i = 0; /* NULL */; i++, direc++) {
396 			if (i >= direc_hdr->number) {
397 				if (0 == ist->default_action.itm_ptr) {
398 					errno = EILSEQ;
399 					TRACE_MESSAGE('e',
400 					    ("_icv_iconv:error=%d\n", errno));
401 					return ((size_t)(-1));
402 				}
403 
404 
405 
406 				action = ist->default_action;
407 				type = ((itm_tbl_hdr_t *)(ADDR(action)))->type;
408 				TRACE_MESSAGE('E',
409 				    ("escape seq (default action=%6p, "
410 				    "type=%ld) executing\n",
411 				    action.itm_ptr, type));
412 			} else if (0 != direc->condition.itm_ptr) {
413 				retval = eval_cond_tbl(ist, direc->condition,
414 				    inbuf, inbytesleft, *outbytesleft, direc);
415 				if ((size_t)(0) == retval) {
416 					continue;
417 				} else if ((size_t)(-1) == retval) {
418 					return	(retval);
419 				} else if ((size_t)(2) == retval) {
420 					goto retry_cond_eval;
421 				}
422 				action = direc->action;
423 				type = ((itm_tbl_hdr_t *)(ADDR(action)))->type;
424 			} else {
425 				action = direc->action;
426 				type = ((itm_tbl_hdr_t *)(ADDR(action)))->type;
427 			}
428 
429 			TRACE_MESSAGE('a',
430 			    ("inbytesleft=%ld; type=%ld:action=%p\n",
431 			    *inbytesleft, type, action.itm_ptr));
432 			switch (ITM_TBL_MASK & type) {
433 			case ITM_TBL_OP:
434 				retval = eval_op_tbl(ist, action,
435 				    inbuf, inbytesleft, outbuf, outbytesleft);
436 				if ((size_t)(-1) == retval) {
437 					return	(retval);
438 				}
439 				break;
440 			case ITM_TBL_DIREC:
441 				ist->direc = ADDR(action);
442 				break;
443 			case ITM_TBL_MAP:
444 				switch (type) {
445 				case ITM_TBL_MAP_INDEX_FIXED_1_1:
446 				case ITM_TBL_MAP_INDEX_FIXED:
447 					retval = map_i_f(ADDR(action),
448 					    inbuf, inbytesleft,
449 					    outbuf, outbytesleft, 1);
450 					break;
451 				case ITM_TBL_MAP_HASH:
452 					retval = map_h_l(ADDR(action),
453 					    inbuf, inbytesleft,
454 					    outbuf, outbytesleft, 1);
455 					break;
456 				case ITM_TBL_MAP_DENSE_ENC:
457 					retval = map_d_e_l(ADDR(action),
458 					    inbuf, inbytesleft,
459 					    outbuf, outbytesleft, 1);
460 					break;
461 				case ITM_TBL_MAP_LOOKUP:
462 					retval = map_l_f(ADDR(action),
463 					    inbuf, inbytesleft,
464 					    outbuf, outbytesleft, 1);
465 					break;
466 				default:
467 					errno = ELIBBAD;
468 					TRACE_MESSAGE('e',
469 					    ("_icv_iconv:error=%d\n", errno));
470 					return ((size_t)(-1));
471 
472 				}
473 				if ((size_t)(-1) == retval) {
474 					return	(retval);
475 				}
476 				break;
477 			default:	/* never */
478 				errno = ELIBBAD;
479 				TRACE_MESSAGE('e',
480 				    ("_icv_iconv:error=%d\n", errno));
481 				return ((size_t)(-1));
482 			}
483 			break;
484 		}
485 	}
486 	return	(retval);
487 }
488 
489 
490 
491 /*
492  * map-indexed-fixed
493  */
494 static size_t
map_i_f(itm_tbl_hdr_t * tbl_hdr,const unsigned char ** inbuf,size_t * inbytesleft,unsigned char ** outbuf,size_t * outbytesleft,long once)495 map_i_f(
496 	itm_tbl_hdr_t		*tbl_hdr,
497 	const unsigned char	**inbuf,
498 	size_t			*inbytesleft,
499 	unsigned char		**outbuf,
500 	size_t			*outbytesleft,
501 	long			once)
502 {
503 	itm_map_idx_fix_hdr_t	*map_hdr;
504 	long			i;
505 	unsigned char		c;
506 	unsigned long		j;
507 	const unsigned char	*p;
508 
509 	TRACE_MESSAGE('i', ("map_i_f\n"));
510 
511 	map_hdr = (itm_map_idx_fix_hdr_t *)(tbl_hdr + 1);
512 
513 	do {
514 		if (*inbytesleft < map_hdr->source_len) {
515 			errno = EINVAL;
516 			TRACE_MESSAGE('e', ("map_i_f:error=%d\n", errno));
517 			return ((size_t)(-1));
518 		}
519 
520 		j = 0;
521 		for (i = 0; i < map_hdr->source_len; i++) {
522 			GET(c);
523 			j = ((j << 8) | c);
524 		}
525 
526 		if (((j < map_hdr->start.itm_ptr) ||
527 		    (map_hdr->end.itm_ptr < j)) &&
528 		    (0 < map_hdr->default_error)) {
529 			errno = EILSEQ;
530 			(*inbuf) = (void*) ((*inbuf) - map_hdr->source_len);
531 			(*inbytesleft) += map_hdr->source_len;
532 			TRACE_MESSAGE('e', ("map_i_f:error=%d\n", errno));
533 			return ((size_t)(-1));
534 		}
535 
536 		if (*outbytesleft < map_hdr->result_len) {
537 			errno = E2BIG;
538 			(*inbuf) = (void *)((*inbuf) - map_hdr->source_len);
539 			(*inbytesleft) += map_hdr->source_len;
540 			TRACE_MESSAGE('e', ("map_i_f:error=%d\n", errno));
541 			return ((size_t)(-1));
542 		}
543 
544 		if ((j < map_hdr->start.itm_ptr) ||
545 		    (map_hdr->end.itm_ptr < j)) {
546 			if (0 == map_hdr->default_error) {
547 				p = (((unsigned char *)(map_hdr + 1)) +
548 				    (map_hdr->result_len * (tbl_hdr->number)));
549 				for (i = 0; i < map_hdr->result_len; i++) {
550 					PUT(*(p + i));
551 				}
552 			} else {
553 				p = ((*inbuf) - map_hdr->source_len);
554 				for (i = 0; i < map_hdr->source_len; i++) {
555 					PUT(*(p + i));
556 				}
557 			}
558 		} else {
559 			char	*map_error;
560 			map_error = (((char *)(map_hdr + 1)) +
561 			    (map_hdr->result_len * (tbl_hdr->number)) +
562 			    (j - map_hdr->start.itm_ptr));
563 			if (0 == map_hdr->default_error) {
564 				map_error = (void *)
565 				    (map_error + map_hdr->result_len);
566 			}
567 			if (((1 == map_hdr->default_error) ||
568 			    (0 < map_hdr->error_num)) &&
569 			    (0 != *(map_error))) {
570 				errno = EILSEQ;
571 				(*inbuf) = (void *)
572 				    ((*inbuf) - map_hdr->source_len);
573 				(*inbytesleft) += map_hdr->source_len;
574 				TRACE_MESSAGE('e',
575 				    ("map_i_f:error=%d\n", errno));
576 				return ((size_t)(-1));
577 			}
578 			p = (((unsigned char *)(map_hdr + 1)) +
579 			    (map_hdr->result_len *
580 			    (j - map_hdr->start.itm_ptr)));
581 			for (i = 0; i < map_hdr->result_len; i++) {
582 				PUT(*(p + i));
583 			}
584 		}
585 	} while ((0 < *inbytesleft) && (0 == once));
586 
587 	return (size_t)(0);
588 }
589 
590 
591 /*
592  * map-lookup-fixed
593  */
594 static size_t
map_l_f(itm_tbl_hdr_t * tbl_hdr,const unsigned char ** inbuf,size_t * inbytesleft,unsigned char ** outbuf,size_t * outbytesleft,long once)595 map_l_f(
596 	itm_tbl_hdr_t	*tbl_hdr,
597 	const unsigned char	**inbuf,
598 	size_t		*inbytesleft,
599 	unsigned char	**outbuf,
600 	size_t		*outbytesleft,
601 	long		once)
602 {
603 	itm_map_lookup_hdr_t	*map_hdr;
604 	long			i;
605 	unsigned char		*map;
606 	const unsigned char	*p;
607 	long			high;
608 	long			mid;
609 	long			low;
610 	long			result;
611 	itm_size_t		pair_size;
612 
613 	TRACE_MESSAGE('i', ("map_l_f\n"));
614 
615 	map_hdr = (itm_map_lookup_hdr_t *)(tbl_hdr + 1);
616 	map = (unsigned char *)(map_hdr + 1);
617 	pair_size = map_hdr->source_len + 1 + map_hdr->result_len;
618 
619 	do {
620 		if (*inbytesleft < map_hdr->source_len) {
621 			errno = EINVAL;
622 			TRACE_MESSAGE('e', ("map_l_f:error=%d\n", errno));
623 			return ((size_t)(-1));
624 		}
625 
626 		for (low = 0, high = tbl_hdr->number; low < high; ) {
627 			mid = (low + high) / 2;
628 			p = map + (pair_size * mid);
629 			for (i = 0, result = 0; i < map_hdr->source_len;
630 			    i++, p++) {
631 				if (*(unsigned char *)(*inbuf + i) < *p) {
632 					result = -1;
633 					break;
634 				}
635 				if (*p < *(unsigned char *)(*inbuf + i)) {
636 					result = 1;
637 					break;
638 				}
639 			}
640 			if (result < 0) {
641 				high = mid;
642 			} else if (0 < result) {
643 				low = mid + 1;
644 			} else { /* 0 == result */
645 				break;
646 			}
647 		}
648 
649 		if (0 != result) {
650 			if (map_hdr->default_error < 0) {
651 				p = *inbuf;
652 			} else if (0 == map_hdr->default_error) {
653 				p = map + (pair_size * tbl_hdr->number) +
654 				    map_hdr->source_len + 1;
655 			} else if (0 < map_hdr->default_error) {
656 				errno = EILSEQ;
657 				TRACE_MESSAGE('e', ("map_l_f:error=%d\n",
658 				    errno));
659 				return ((size_t)(-1));
660 			}
661 		} else {
662 			if (0 != (*p)) {
663 				errno = EILSEQ;
664 				TRACE_MESSAGE('e', ("map_l_f:error=%d\n",
665 				    errno));
666 				return ((size_t)(-1));
667 			}
668 			p++;
669 		}
670 
671 		if (*outbytesleft < map_hdr->result_len) {
672 			errno = E2BIG;
673 			TRACE_MESSAGE('e', ("map_l_f:error=%d\n", errno));
674 			return ((size_t)(-1));
675 		}
676 		DISCARD(map_hdr->source_len);
677 
678 		for (i = 0; i < map_hdr->result_len; i++) {
679 			PUT(*(p + i));
680 		}
681 	} while ((0 < *inbytesleft) && (0 == once));
682 
683 	return ((size_t)(0));
684 }
685 
686 
687 /*
688  * map-hash-lookup
689  */
690 static size_t
map_h_l(itm_tbl_hdr_t * tbl_hdr,const unsigned char ** inbuf,size_t * inbytesleft,unsigned char ** outbuf,size_t * outbytesleft,long once)691 map_h_l(
692 	itm_tbl_hdr_t	*tbl_hdr,
693 	const unsigned char	**inbuf,
694 	size_t		*inbytesleft,
695 	unsigned char	**outbuf,
696 	size_t		*outbytesleft,
697 	long		once)
698 {
699 	itm_map_hash_hdr_t	*map_hdr;
700 	long			i;
701 	unsigned char	*map_error;
702 	unsigned char	*map_hash;
703 	unsigned char	*map_of;
704 	const unsigned char	*p;
705 	const unsigned char	*q;
706 	long			high;
707 	long			mid;
708 	long			low;
709 	long			result;
710 	itm_size_t		pair_size;
711 	itm_size_t		hash_value;
712 	itm_size_t		source_len;
713 	itm_size_t		result_len;
714 
715 	TRACE_MESSAGE('i', ("map_hash\n"));
716 
717 	map_hdr = (itm_map_hash_hdr_t *)(tbl_hdr + 1);
718 	map_error = (unsigned char *)(map_hdr + 1);
719 	map_hash = (map_error + map_hdr->hash_tbl_num);
720 	map_of = map_hash + map_hdr->hash_tbl_size;
721 	pair_size = map_hdr->source_len + 1 + map_hdr->result_len;
722 	source_len = map_hdr->source_len;
723 	result_len = map_hdr->result_len;
724 
725 	do {
726 		if (*inbytesleft < source_len) {
727 			errno = EINVAL;
728 			TRACE_MESSAGE('e', ("map_h_l:error=%d\n", errno));
729 			return ((size_t)(-1));
730 		}
731 
732 		result = 1;
733 		q = *inbuf;
734 		hash_value = hash((const char *)(q), source_len,
735 		    map_hdr->hash_tbl_num);
736 		p = map_hash + (pair_size * hash_value);
737 		if (1 == *(map_error + hash_value)) {
738 			for (i = 0, result = 0; i < source_len; i++) {
739 				if (*(q + i) != *(p++)) {
740 					result = -2;
741 					break;
742 				}
743 			}
744 			TRACE_MESSAGE('G',
745 			    ("(h=%d): find pair without conflict\n",
746 			    hash_value));
747 		} else if (0 == *(map_error + hash_value)) {
748 			TRACE_MESSAGE('G', ("(h=%d): No Pair\n", hash_value));
749 			result = -3;
750 		} else /* if (0 < *(map_error + hash_value)) */ {
751 			for (i = 0, result = 0; i < source_len; i++) {
752 				if (*(q + i) != *(p++)) {
753 					result = 1;
754 					break;
755 				}
756 			}
757 			if (0 < result) {
758 				for (low = 0, high = map_hdr->hash_of_num;
759 				    low < high; /* NOP */) {
760 					mid = (low + high) / 2;
761 					p = map_of + (pair_size * mid);
762 					for (i = 0, result = 0;
763 					    i < source_len;
764 					    i++, p++) {
765 						if (*(q + i) < *p) {
766 							result = -1;
767 							break;
768 						}
769 						if (*p < *(q + i)) {
770 							result = 1;
771 							break;
772 						}
773 					}
774 					if (result < 0) {
775 						high = mid;
776 					} else if (0 < result) {
777 						low = mid + 1;
778 					} else { /* 0 == result */
779 						TRACE_MESSAGE('G', ("(h=%d): "
780 						    "find data on out of "
781 						    "hashtable with CONFLICT\n",
782 						    hash_value));
783 						break;
784 					}
785 				}
786 			}
787 		}
788 		if (0 != result) {
789 			if (map_hdr->default_error < 0) {
790 				p = q;
791 			} else if (0 == map_hdr->default_error) {
792 				p = map_of + map_hdr->hash_of_size;
793 			} else if (0 < map_hdr->default_error) {
794 				TRACE_MESSAGE('G', ("(h=%d): NO PAIR\n",
795 				    hash_value));
796 				errno = EILSEQ;
797 				TRACE_MESSAGE('e',
798 				    ("map_h_l:error=%d\n", errno));
799 				return ((size_t)(-1));
800 			}
801 		} else {
802 			if (0 != (*p)) {
803 				errno = EILSEQ;
804 				TRACE_MESSAGE('G', ("	      : error pair\n"));
805 				TRACE_MESSAGE('e', ("map_l_f:error\n", errno));
806 				return ((size_t)(-1));
807 			}
808 			p++;
809 		}
810 
811 		if (*outbytesleft < result_len) {
812 			errno = E2BIG;
813 			TRACE_MESSAGE('e', ("map_h_l:error=%d\n", errno));
814 			return ((size_t)(-1));
815 		}
816 		DISCARD(source_len);
817 
818 		for (i = 0; i < result_len; i++) {
819 			PUT(*(p + i));
820 		}
821 	} while ((0 < *inbytesleft) && (0 == once));
822 
823 	return ((size_t)(0));
824 }
825 
826 
827 /*
828  * map-dense_encoding-lookup
829  */
830 static size_t
map_d_e_l(itm_tbl_hdr_t * tbl_hdr,const unsigned char ** inbuf,size_t * inbytesleft,unsigned char ** outbuf,size_t * outbytesleft,long once)831 map_d_e_l(
832 	itm_tbl_hdr_t		*tbl_hdr,
833 	const unsigned char	**inbuf,
834 	size_t			*inbytesleft,
835 	unsigned char		**outbuf,
836 	size_t			*outbytesleft,
837 	long			once)
838 {
839 	itm_map_dense_enc_hdr_t	*map_hdr;
840 	long			i;
841 	itm_num_t		j;
842 	const unsigned char	*p;
843 	unsigned char		*map_ptr;
844 	unsigned char		*map_error;
845 	unsigned char		*byte_seq_min;
846 	unsigned char		*byte_seq_max;
847 
848 	TRACE_MESSAGE('i', ("map_d_e_l\n"));
849 
850 	map_hdr = (itm_map_dense_enc_hdr_t *)(tbl_hdr + 1);
851 	map_ptr = ((unsigned char *)(map_hdr + 1) + map_hdr->source_len +
852 	    map_hdr->source_len);
853 	map_error = (map_ptr + (tbl_hdr->number * map_hdr->result_len));
854 	if (0 == map_hdr->default_error) {
855 		map_error = (void *)(map_error + map_hdr->result_len);
856 	}
857 	byte_seq_min = (unsigned char *)(map_hdr + 1);
858 	byte_seq_max = byte_seq_min + map_hdr->source_len;
859 
860 	do {
861 		if (*inbytesleft < map_hdr->source_len) {
862 			errno = EINVAL;
863 			TRACE_MESSAGE('e', ("map_d_e_l:error=%d\n", errno));
864 			return ((size_t)(-1));
865 		}
866 
867 		j = hash_dense_encoding(*inbuf, map_hdr->source_len,
868 		    byte_seq_min, byte_seq_max);
869 
870 		if (((j < 0) || (tbl_hdr->number < j)) &&
871 		    (0 < map_hdr->default_error)) {
872 			errno = EILSEQ;
873 			TRACE_MESSAGE('e', ("map_d_e_l:error=%d\n", errno));
874 			return ((size_t)(-1));
875 		}
876 
877 		if (*outbytesleft < map_hdr->result_len) {
878 			errno = E2BIG;
879 			TRACE_MESSAGE('e', ("map_d_e_l:error=%d\n", errno));
880 			return ((size_t)(-1));
881 		}
882 
883 		if ((j < 0) || (tbl_hdr->number < j)) {
884 			if (0 == map_hdr->default_error) {
885 				p = (map_ptr + (tbl_hdr->number *
886 				    map_hdr->result_len));
887 				for (i = 0; i < map_hdr->result_len; i++) {
888 					PUT(*(p + i));
889 				}
890 			} else {
891 				p = *inbuf;
892 				for (i = 0; i < map_hdr->source_len; i++) {
893 					PUT(*(p + i));
894 				}
895 			}
896 		} else {
897 			if ((1 == map_hdr->default_error) ||
898 			    (0 < map_hdr->error_num)) {
899 				if (0 != *(map_error + j)) {
900 					errno = EILSEQ;
901 					TRACE_MESSAGE('e',
902 					    ("map_d_e_l:error=%d\n", errno));
903 					return ((size_t)(-1));
904 				}
905 			}
906 			p = (map_ptr + (map_hdr->result_len * j));
907 			for (i = 0; i < map_hdr->result_len; i++) {
908 				PUT(*(p + i));
909 			}
910 		}
911 		DISCARD(map_hdr->source_len);
912 	} while ((0 < *inbytesleft) && (0 == once));
913 
914 	return ((size_t)(0));
915 }
916 
917 
918 
919 /*
920  * Evaluate condition table
921  *
922  */
923 static size_t
eval_cond_tbl(icv_state_t * ist,itm_place_t cond_place,const unsigned char ** inbuf,size_t * inbytesleft,size_t outbytesleft,itm_direc_t * direc)924 eval_cond_tbl(icv_state_t *ist, itm_place_t cond_place,
925     const unsigned char **inbuf, size_t *inbytesleft, size_t outbytesleft,
926     itm_direc_t *direc)
927 {
928 	itm_tbl_hdr_t		*cond_hdr;
929 	itm_cond_t		*cond;
930 	long			i;
931 	long			j;
932 	long			k;
933 	size_t			retval;
934 	itm_tbl_hdr_t		*rth;
935 	itm_range_hdr_t		*rtsh;
936 	unsigned char		*p;
937 	itm_tbl_hdr_t		*eth;
938 	itm_escapeseq_hdr_t	*eh;
939 	itm_data_t		*d;
940 	const unsigned char	*ip;
941 	size_t			ileft;
942 
943 	retval = 0;
944 	ip =	*inbuf;
945 	ileft = *inbytesleft;
946 	cond_hdr = ADDR(cond_place);
947 	cond = (itm_cond_t *)(cond_hdr + 1);
948 	for (i = 0; i < cond_hdr->number; i++, cond++) {
949 		switch (cond->type) {
950 		case ITM_COND_BETWEEN:
951 			rth = ADDR(cond->operand.place);
952 			rtsh = (itm_range_hdr_t *)(rth + 1);
953 			if (ileft < rtsh->len) {
954 				errno = EINVAL;
955 				TRACE_MESSAGE('e', ("eval_cond_tbl:error=%d\n",
956 				    errno));
957 				retval = ((size_t)(-1));
958 				goto eval_cond_return;
959 			}
960 			p = (unsigned char *)(rtsh + 1);
961 			retval = 0;
962 			for (j = 0; j < rth->number;
963 			    j++,  p = (void *)(p + (2 * rtsh->len))) {
964 				retval = 1;
965 				for (k = 0; k < rtsh->len; k++) {
966 					if ((*(ip + k) < *(p + k)) ||
967 					    (*(p + rtsh->len + k) <
968 					    *(ip + k))) {
969 						retval = 0;
970 						break;
971 					}
972 				}
973 				if (1 == retval) {
974 					break;
975 				}
976 			}
977 			if (0 == retval) {
978 				TRACE_MESSAGE('b',
979 				    ("out of between (%p) len= rtsh=%ld\n",
980 				    *ip, rtsh->len));
981 				goto eval_cond_return;
982 			}
983 			break; /* continue */
984 		case ITM_COND_ESCAPESEQ:
985 			/*
986 			 * if escape sequence occur,
987 			 * change ist->default_action and return 2.
988 			 * never return 1.
989 			 */
990 			retval = 0;
991 			eth = ADDR(cond->operand.place);
992 			eh = (itm_escapeseq_hdr_t *)(eth + 1);
993 			if (0 == ist->default_action.itm_ptr) {
994 				ist->default_action = direc->action;
995 				TRACE_MESSAGE('E',
996 				    ("escape seq (default action=%6p, "
997 				    "type=%ld) set\n",
998 				    direc->action.itm_ptr, ((itm_tbl_hdr_t *)
999 				    (ADDR(direc->action)))->type));
1000 			}
1001 			retval = 0;
1002 			if (*inbytesleft < eh->len_min) {
1003 				break;
1004 			}
1005 			for (j = 0, d = (itm_data_t *)(eh + 1);
1006 			    j < eth->number;
1007 			    j++, d++) {
1008 				if (*inbytesleft < d->size) {
1009 					continue;
1010 				}
1011 				if (0 == memcmp(*inbuf, DADDR(d), d->size)) {
1012 					TRACE_MESSAGE('E',
1013 					    ("escape seq: discard=%ld chars\n",
1014 					    d->size));
1015 					TRACE_MESSAGE('E',
1016 					    ("escape seq (default "
1017 					    "action=%6p, type=%ld) set\n",
1018 					    direc->action.itm_ptr,
1019 					    ((itm_tbl_hdr_t *)
1020 					    (ADDR(direc->action)))->type));
1021 					ist->default_action = direc->action;
1022 					DISCARD(d->size);
1023 					retval = 2;
1024 					goto eval_cond_return;
1025 				}
1026 			}
1027 			if (0 == retval) {
1028 				goto eval_cond_return;
1029 			}
1030 			break; /* continue */
1031 		case ITM_COND_EXPR:
1032 			retval = eval_expr(ist, cond->operand.place,
1033 			    *inbytesleft, ip, outbytesleft);
1034 			if (0 == retval) {
1035 				goto eval_cond_return;
1036 			} else {
1037 				retval = 1;
1038 			}
1039 			break; /* continue */
1040 		default:
1041 			TRACE_MESSAGE('e', ("eval_cond_tbl:illegal cond=%d\n",
1042 			    cond->type));
1043 			retval = (size_t)-1;
1044 			goto eval_cond_return;
1045 		}
1046 	}
1047 
1048 eval_cond_return:
1049 	return (retval);
1050 }
1051 
1052 /*
1053  * Evaluate operation table
1054  *
1055  */
1056 static size_t
eval_op_tbl(icv_state_t * ist,itm_place_t op_tbl_place,const unsigned char ** inbuf,size_t * inbytesleft,unsigned char ** outbuf,size_t * outbytesleft)1057 eval_op_tbl(
1058 	icv_state_t	*ist,
1059 	itm_place_t	op_tbl_place,
1060 	const unsigned char	**inbuf,
1061 	size_t		*inbytesleft,
1062 	unsigned char	**outbuf,
1063 	size_t		*outbytesleft)
1064 {
1065 	itm_tbl_hdr_t	*op_hdr;
1066 	itm_op_t	*operation;
1067 	itm_place2_t	op_place;
1068 	size_t		retval;
1069 	long		i;
1070 
1071 	retval = 0;
1072 
1073 #if defined(OP_DEPTH_MAX)
1074 	if (OP_DEPTH_MAX <= ist->op_depth) {
1075 		errno = ELIBBAD;
1076 		TRACE_MESSAGE('e', ("eval_op_tbl:error=%d\n", errno));
1077 		return	(RETVALERR);
1078 	}
1079 	ist->op_depth += 1;
1080 #endif /* OP_DEPTH_MAX */
1081 
1082 	op_hdr = ADDR(op_tbl_place);
1083 	operation = (itm_op_t *)(op_hdr + 1);
1084 
1085 	op_place = op_tbl_place.itm_ptr + (sizeof (itm_tbl_hdr_t));
1086 	for (i = 0; i < op_hdr->number; i++, operation++,
1087 	    op_place += (sizeof (itm_op_t))) {
1088 		TRACE_MESSAGE('O', ("eval_op_tbl: %ld %p\n", i, op_place));
1089 		retval = eval_op(ist, op_place, inbuf, inbytesleft,
1090 		    outbuf, outbytesleft);
1091 		if (((long)(retval)) < 0) {
1092 #if defined(OP_DEPTH_MAX)
1093 			ist->op_depth -= 1;
1094 #endif /* OP_DEPTH_MAX */
1095 			switch (retval) {
1096 			case RETVALERR:
1097 				return	(retval);
1098 			case RETVALRET:
1099 				if (0 == op_hdr->name.itm_ptr) {
1100 					return	(RETVALRET);
1101 				} else {
1102 					return (0);
1103 				}
1104 			}
1105 		}
1106 	}
1107 #if defined(OP_DEPTH_MAX)
1108 	ist->op_depth -= 1;
1109 #endif /* OP_DEPTH_MAX */
1110 	return	(retval);
1111 }
1112 
1113 
1114 /*
1115  * Evaluate single operation
1116  *
1117  */
1118 static size_t
eval_op(icv_state_t * ist,itm_place2_t op_place,const unsigned char ** inbuf,size_t * inbytesleft,unsigned char ** outbuf,size_t * outbytesleft)1119 eval_op(
1120 	icv_state_t		*ist,
1121 	itm_place2_t		op_place,
1122 	const unsigned char	**inbuf,
1123 	size_t			*inbytesleft,
1124 	unsigned char		**outbuf,
1125 	size_t			*outbytesleft)
1126 {
1127 	size_t			retval;
1128 	itm_num_t		num;
1129 	itm_op_t		*operation;
1130 	itm_expr_t		*expr;
1131 	itm_num_t		c;
1132 	itm_num_t		i;
1133 	itm_size_t		z;
1134 	unsigned char		*p;
1135 	itm_expr_t		*expr0;
1136 	itm_tbl_hdr_t		*h;
1137 	itm_type_t		t;
1138 
1139 #define	EVAL_EXPR(n)							\
1140 	(expr0 = ADDR(operation->data.operand[(n)]),			\
1141 		(itm_num_t)((expr0->type == ITM_EXPR_INT) ?		\
1142 		expr0->data.itm_exnum :					\
1143 		((expr0->type == ITM_EXPR_REG) ?			\
1144 		REG(expr0->data.itm_exnum) :				\
1145 		((expr0->type == ITM_EXPR_IN_VECTOR_D) ?		\
1146 		((expr0->data.itm_exnum < 0) ?				\
1147 		(((-1) == expr0->data.itm_exnum) ? *inbytesleft : 0) :	\
1148 		((expr0->data.itm_exnum < *inbytesleft) ?		\
1149 		(*(uchar_t *)(*inbuf + expr0->data.itm_exnum)) : 0)):	\
1150 		eval_expr(ist, operation->data.operand[(n)],		\
1151 		*inbytesleft, *inbuf, *outbytesleft)))))
1152 
1153 	retval = 0;
1154 
1155 	operation = (itm_op_t *)ADDR2(op_place);
1156 
1157 	switch (operation->type) {
1158 	case ITM_OP_EXPR:
1159 		num = eval_expr(ist, operation->data.operand[0],
1160 		    *inbytesleft, *inbuf, *outbytesleft);
1161 		TRACE_MESSAGE('o', ("ITM_OP_EXPR: %ld\n", retval));
1162 		break;
1163 	case ITM_OP_ERROR:
1164 		num = eval_expr(ist, operation->data.operand[0],
1165 		    *inbytesleft, *inbuf, *outbytesleft);
1166 		errno = (int)num;
1167 		TRACE_MESSAGE('o', ("ITM_OP_ERROR: %ld\n", num));
1168 		retval = (size_t)(-1);
1169 		break;
1170 	case ITM_OP_ERROR_D:
1171 		errno = (int)operation->data.itm_opnum;
1172 		TRACE_MESSAGE('o', ("ITM_OP_ERROR_D: %d\n", errno));
1173 		retval = (size_t)(-1);
1174 		break;
1175 	case ITM_OP_OUT:
1176 		expr = ADDR(operation->data.operand[0]);
1177 		if ((*outbytesleft) == 0) {
1178 			errno = E2BIG;
1179 			TRACE_MESSAGE('e', ("eval_op:error=%d\n", errno));
1180 			return ((size_t)(-1));
1181 		}
1182 		c = eval_expr(ist, operation->data.operand[0],
1183 		    *inbytesleft, *inbuf, *outbytesleft);
1184 		PUT((uchar_t)c);
1185 		retval = *inbytesleft;
1186 		TRACE_MESSAGE('o', ("ITM_OP_OUT: %ld %ld\n", c, *inbytesleft));
1187 		break;
1188 	case ITM_OP_OUT_D:
1189 		expr = ADDR(operation->data.operand[0]);
1190 		if ((*outbytesleft) == 0) {
1191 			errno = E2BIG;
1192 			TRACE_MESSAGE('e', ("eval_op:error=%d\n", errno));
1193 			return ((size_t)(-1));
1194 		}
1195 		PUT(0xff & (expr->data.itm_exnum));
1196 		break;
1197 	case ITM_OP_OUT_S:
1198 		expr = ADDR(operation->data.operand[0]);
1199 		if ((*outbytesleft) == 0) {
1200 			errno = E2BIG;
1201 			TRACE_MESSAGE('e', ("eval_op:error=%d\n", errno));
1202 			return ((size_t)(-1));
1203 		}
1204 		z = expr->data.value.size;
1205 		if (*outbytesleft < z) {
1206 			errno = E2BIG;
1207 			TRACE_MESSAGE('e', ("eval_op:error=%d\n", errno));
1208 			return ((size_t)(-1));
1209 		}
1210 		p = DADDR(&(expr->data.value));
1211 		for (; 0 < z; --z, p++) {
1212 			PUT(*p);
1213 		}
1214 		break;
1215 	case ITM_OP_OUT_R:
1216 		expr = ADDR(operation->data.operand[0]);
1217 		if ((*outbytesleft) == 0) {
1218 			errno = E2BIG;
1219 			TRACE_MESSAGE('e', ("eval_op:error=%d\n", errno));
1220 			return ((size_t)(-1));
1221 		}
1222 		c = REG(expr->data.itm_exnum);
1223 		PUT((uchar_t)c);
1224 		break;
1225 	case ITM_OP_OUT_INVD:
1226 		expr = ADDR(operation->data.operand[0]);
1227 		if ((*outbytesleft) == 0) {
1228 			errno = E2BIG;
1229 			TRACE_MESSAGE('e', ("eval_op:error=%d\n", errno));
1230 			return ((size_t)(-1));
1231 		}
1232 		z = (((0 <= expr->data.itm_exnum) &&
1233 		    (expr->data.itm_exnum < *inbytesleft)) ?
1234 		    (*((unsigned char *)(*inbuf + expr->data.itm_exnum))) :
1235 		    (((-1) == expr->data.itm_exnum) ? *inbytesleft : 0));
1236 		PUT((uchar_t)z);
1237 		break;
1238 	case ITM_OP_DISCARD:
1239 #if defined(EVAL_EXPR)
1240 		num = EVAL_EXPR(0);
1241 #else /* !defined(EVAL_EXPR) */
1242 		num = eval_expr(ist, operation->data.operand[0],
1243 		    *inbytesleft, *inbuf, *outbytesleft);
1244 #endif /* defined(EVAL_EXPR) */
1245 		TRACE_MESSAGE('o', ("ITM_OP_DISCARD: %ld\n", num));
1246 #if defined(DISCARD)
1247 		DISCARD((num <= *inbytesleft) ? ((ulong_t)num) : *inbytesleft);
1248 #else /* defined(DISCARD) */
1249 		for (num = ((num <= *inbytesleft) ? num : *inbytesleft);
1250 		    0 < num; --num) {
1251 			GET(c);
1252 		}
1253 #endif /* defined(DISCARD) */
1254 		break;
1255 	case ITM_OP_DISCARD_D:
1256 		num = operation->data.itm_opnum;
1257 		TRACE_MESSAGE('o', ("ITM_OP_DISCARD_D: %ld\n", num));
1258 #if defined(DISCARD)
1259 		DISCARD((num <= *inbytesleft) ? num : *inbytesleft);
1260 #else /* defined(DISCARD) */
1261 		for (num = ((num <= *inbytesleft) ? num : *inbytesleft);
1262 		    0 < num; --num) {
1263 			GET(c);
1264 		}
1265 #endif /* defined(DISCARD) */
1266 		break;
1267 	case ITM_OP_IF:
1268 		c = eval_expr(ist, operation->data.operand[0],
1269 		    *inbytesleft, *inbuf, *outbytesleft);
1270 		TRACE_MESSAGE('o', ("ITM_OP_IF: %ld\n", c));
1271 		if (c) {
1272 			retval = eval_op_tbl(ist, operation->data.operand[1],
1273 			    inbuf, inbytesleft, outbuf, outbytesleft);
1274 		}
1275 		break;
1276 	case ITM_OP_IF_ELSE:
1277 		c = eval_expr(ist, operation->data.operand[0],
1278 		    *inbytesleft, *inbuf, *outbytesleft);
1279 		TRACE_MESSAGE('o', ("ITM_OP_IF_ELSE: %ld\n", c));
1280 		if (c) {
1281 			retval = eval_op_tbl(ist, operation->data.operand[1],
1282 			    inbuf, inbytesleft, outbuf, outbytesleft);
1283 		} else {
1284 			retval = eval_op_tbl(ist, operation->data.operand[2],
1285 			    inbuf, inbytesleft, outbuf, outbytesleft);
1286 		}
1287 		break;
1288 	case ITM_OP_DIRECTION:
1289 		TRACE_MESSAGE('o', ("ITM_OP_DIRECTION: %p\n",
1290 		    operation->data.operand[0].itm_ptr));
1291 		ist->direc = ADDR(operation->data.operand[0]);
1292 		return ((size_t)(-2));
1293 	case ITM_OP_MAP:
1294 		TRACE_MESSAGE('o', ("ITM_OP_MAP: %p\n",
1295 		    operation->data.operand[0].itm_ptr));
1296 		i = 0;
1297 		if (0 != operation->data.operand[1].itm_ptr) {
1298 #if defined(EVAL_EXPR)
1299 			i = EVAL_EXPR(1);
1300 #else /* !defined(EVAL_EXPR) */
1301 			i = eval_expr(ist, operation->data.operand[1],
1302 			    *inbytesleft, *inbuf, *outbytesleft);
1303 #endif /* defined(EVAL_EXPR) */
1304 			(*inbytesleft) -= i;
1305 			(*inbuf) += i;
1306 		}
1307 
1308 		/*
1309 		 * Based on what is the maptype, we call the corresponding
1310 		 * mapping function.
1311 		 */
1312 		h = ADDR(operation->data.operand[0]);
1313 		t = h->type;
1314 		switch (t) {
1315 		case ITM_TBL_MAP_INDEX_FIXED:
1316 		case ITM_TBL_MAP_INDEX_FIXED_1_1:
1317 			retval = map_i_f(h, inbuf, inbytesleft,
1318 			    outbuf, outbytesleft, 1);
1319 			break;
1320 		case ITM_TBL_MAP_HASH:
1321 			retval = map_h_l(h, inbuf, inbytesleft,
1322 			    outbuf, outbytesleft, 1);
1323 			break;
1324 		case ITM_TBL_MAP_DENSE_ENC:
1325 			retval = map_d_e_l(h, inbuf, inbytesleft,
1326 			    outbuf, outbytesleft, 1);
1327 			break;
1328 		case ITM_TBL_MAP_LOOKUP:
1329 			retval = map_l_f(h, inbuf, inbytesleft,
1330 			    outbuf, outbytesleft, 1);
1331 			break;
1332 		default:
1333 			/*
1334 			 * This should not be possible, but in case we
1335 			 * have an incorrect maptype, don't fall back to
1336 			 * map_i_f(). Instead, because it is an error, return
1337 			 * an error. See CR 6622765.
1338 			 */
1339 			errno = EBADF;
1340 			TRACE_MESSAGE('e', ("eval_op:error=%d\n", errno));
1341 			retval = (size_t)-1;
1342 			break;
1343 		}
1344 
1345 		if ((size_t)(-1) == retval) {
1346 			(*outbytesleft) += i;
1347 			(*outbuf) -= i;
1348 		}
1349 		break;
1350 	case ITM_OP_OPERATION:
1351 		TRACE_MESSAGE('o', ("ITM_OP_OPERATION: %p\n",
1352 		    operation->data.operand[0].itm_ptr));
1353 		retval = eval_op_tbl(ist, operation->data.operand[0],
1354 		    inbuf, inbytesleft, outbuf, outbytesleft);
1355 
1356 		break;
1357 	case ITM_OP_INIT:
1358 		TRACE_MESSAGE('o', ("ITM_OP_INIT: %p\n",
1359 		    ist->itm_hdr->op_init_tbl));
1360 		if (0 != ist->itm_hdr->op_init_tbl.itm_ptr) {
1361 			retval = eval_op_tbl(ist, ist->itm_hdr->op_init_tbl,
1362 			    inbuf, inbytesleft, outbuf, outbytesleft);
1363 		} else {
1364 			op_init_default(ist);
1365 			retval = (size_t)-2;
1366 		}
1367 		break;
1368 	case ITM_OP_RESET:
1369 		TRACE_MESSAGE('o', ("ITM_OP_RESET: %p\n",
1370 		    ist->itm_hdr->op_reset_tbl));
1371 		if (0 != ist->itm_hdr->op_reset_tbl.itm_ptr) {
1372 			retval = eval_op_tbl(ist, ist->itm_hdr->op_reset_tbl,
1373 			    inbuf, inbytesleft, outbuf, outbytesleft);
1374 		} else {
1375 			op_reset_default(ist);
1376 			retval = (size_t)-2;
1377 		}
1378 		break;
1379 	case ITM_OP_BREAK:
1380 		TRACE_MESSAGE('o', ("ITM_OP_BREAK\n"));
1381 		return	(RETVALBRK);
1382 	case ITM_OP_RETURN:
1383 		TRACE_MESSAGE('o', ("ITM_OP_RETURN\n"));
1384 		return	(RETVALRET);
1385 	case ITM_OP_PRINTCHR:
1386 		c = eval_expr(ist, operation->data.operand[0], *inbytesleft,
1387 		    *inbuf, *outbytesleft);
1388 		(void) fputc((uchar_t)c, stderr);
1389 		TRACE_MESSAGE('o', ("ITM_OP_PRINTCHR: %ld %ld\n",
1390 		    c, *inbytesleft));
1391 		break;
1392 	case ITM_OP_PRINTHD:
1393 		c = eval_expr(ist, operation->data.operand[0], *inbytesleft,
1394 		    *inbuf, *outbytesleft);
1395 		(void) fprintf(stderr, "%lx", c);
1396 		TRACE_MESSAGE('o', ("ITM_OP_PRINTHD: %ld %ld\n",
1397 		    c, *inbytesleft));
1398 		break;
1399 	case ITM_OP_PRINTINT:
1400 		c = eval_expr(ist, operation->data.operand[0], *inbytesleft,
1401 		    *inbuf, *outbytesleft);
1402 		(void) fprintf(stderr, "%ld", c);
1403 		TRACE_MESSAGE('o', ("ITM_OP_PRINTINT: %ld %ld\n",
1404 		    c, *inbytesleft));
1405 		break;
1406 	default: /* never */
1407 		errno = ELIBBAD;
1408 		TRACE_MESSAGE('e', ("eval_op:error=%d\n", errno));
1409 		return (size_t)(-1);
1410 	}
1411 	return	(retval);
1412 
1413 #undef EVAL_EXPR
1414 }
1415 
1416 
1417 /*
1418  * Evaluate expression
1419  */
1420 static itm_num_t
eval_expr(icv_state_t * ist,itm_place_t expr_place,size_t inbytesleft,const unsigned char * inbuf,size_t outbytesleft)1421 eval_expr(
1422 	icv_state_t		*ist,
1423 	itm_place_t		expr_place,
1424 	size_t			inbytesleft,
1425 	const unsigned char	*inbuf,
1426 	size_t			outbytesleft)
1427 {
1428 	itm_expr_t		*expr;
1429 	itm_expr_t		*expr_op;
1430 	itm_num_t		num;
1431 	unsigned char		*p;
1432 	long			i;
1433 	itm_expr_t		*expr0;
1434 	itm_num_t		num00;
1435 	itm_num_t		num01;
1436 
1437 #define	EVAL_EXPR_E(n) (eval_expr(ist, expr->data.operand[(n)],		\
1438 	inbytesleft, inbuf, outbytesleft))
1439 #define	EVAL_EXPR_D(n)	((itm_num_t)(expr->data.operand[(n)].itm_ptr))
1440 #define	EVAL_EXPR_R(n)	(REG((itm_num_t)(expr->data.operand[(n)].itm_ptr)))
1441 #define	EVAL_EXPR_INVD(n)						\
1442 	((num0 ## n) = ((itm_num_t)(expr->data.operand[(n)].itm_ptr)),	\
1443 		((num0 ## n) < 0) ?					\
1444 		(((-1) == (num0 ## n)) ? inbytesleft : 0) :		\
1445 		(((num0 ## n) < inbytesleft) ?				\
1446 		(*(unsigned char *)(inbuf + (num0 ## n))) : 0))
1447 #define	EVAL_EXPR(n)							\
1448 	(expr0 = ADDR(expr->data.operand[(n)]),				\
1449 		(itm_num_t)((expr0->type == ITM_EXPR_INT) ?		\
1450 		expr0->data.itm_exnum :					\
1451 		((expr0->type == ITM_EXPR_REG) ?			\
1452 		REG(expr0->data.itm_exnum) :				\
1453 		((expr0->type == ITM_EXPR_IN_VECTOR_D) ?		\
1454 		((expr0->data.itm_exnum < 0) ?				\
1455 		(((-1) == expr0->data.itm_exnum) ? inbytesleft : 0) :	\
1456 		((expr0->data.itm_exnum < inbytesleft) ?		\
1457 		(*(uchar_t *)(inbuf + expr0->data.itm_exnum)) : 0)) :	\
1458 		eval_expr(ist, expr->data.operand[(n)],			\
1459 		inbytesleft, inbuf, outbytesleft)))))
1460 
1461 #define	EVAL_OP_BIN_PROTO(op, name, name0, name1)			\
1462 	case ITM_EXPR_##name##_##name0##_##name1:			\
1463 		return (EVAL_EXPR_##name0(0) op EVAL_EXPR_##name1(1));
1464 
1465 #define	EVAL_OP_BIN1(op, name)					\
1466 		EVAL_OP_BIN_PROTO(op, name, E, E)		\
1467 		EVAL_OP_BIN_PROTO(op, name, E, D)		\
1468 		EVAL_OP_BIN_PROTO(op, name, E, R)		\
1469 		EVAL_OP_BIN_PROTO(op, name, E, INVD)
1470 
1471 #define	EVAL_OP_BIN2(op, name)					\
1472 		EVAL_OP_BIN_PROTO(op, name, D, E)		\
1473 		EVAL_OP_BIN_PROTO(op, name, D, D)		\
1474 		EVAL_OP_BIN_PROTO(op, name, D, R)		\
1475 		EVAL_OP_BIN_PROTO(op, name, D, INVD)
1476 
1477 #define	EVAL_OP_BIN3(op, name)					\
1478 		EVAL_OP_BIN_PROTO(op, name, R, E)		\
1479 		EVAL_OP_BIN_PROTO(op, name, R, D)		\
1480 		EVAL_OP_BIN_PROTO(op, name, R, R)		\
1481 		EVAL_OP_BIN_PROTO(op, name, R, INVD)
1482 
1483 #define	EVAL_OP_BIN4(op, name)					\
1484 		EVAL_OP_BIN_PROTO(op, name, INVD, E)		\
1485 		EVAL_OP_BIN_PROTO(op, name, INVD, D)		\
1486 		EVAL_OP_BIN_PROTO(op, name, INVD, R)		\
1487 		EVAL_OP_BIN_PROTO(op, name, INVD, INVD)
1488 
1489 #define	EVAL_OP_BIN_PROTECT_PROTO(op, name, name0, name1)	\
1490 	case ITM_EXPR_##name##_##name0##_##name1:		\
1491 		num = EVAL_EXPR_##name1(1);			\
1492 		if (0 != num) {					\
1493 			return (EVAL_EXPR_##name0(0) op num);	\
1494 		} else {					\
1495 			return (0);				\
1496 		}
1497 
1498 #define	EVAL_OP_BIN_PROTECT1(op, name)				\
1499 		EVAL_OP_BIN_PROTECT_PROTO(op, name, E, E)	\
1500 		EVAL_OP_BIN_PROTECT_PROTO(op, name, E, D)	\
1501 		EVAL_OP_BIN_PROTECT_PROTO(op, name, E, R)	\
1502 		EVAL_OP_BIN_PROTECT_PROTO(op, name, E, INVD)
1503 
1504 #define	EVAL_OP_BIN_PROTECT2(op, name)				\
1505 		EVAL_OP_BIN_PROTECT_PROTO(op, name, D, E)	\
1506 		EVAL_OP_BIN_PROTECT_PROTO(op, name, D, D)	\
1507 		EVAL_OP_BIN_PROTECT_PROTO(op, name, D, R)	\
1508 		EVAL_OP_BIN_PROTECT_PROTO(op, name, D, INVD)
1509 
1510 #define	EVAL_OP_BIN_PROTECT3(op, name)				\
1511 		EVAL_OP_BIN_PROTECT_PROTO(op, name, R, E)	\
1512 		EVAL_OP_BIN_PROTECT_PROTO(op, name, R, D)	\
1513 		EVAL_OP_BIN_PROTECT_PROTO(op, name, R, R)	\
1514 		EVAL_OP_BIN_PROTECT_PROTO(op, name, R, INVD)
1515 
1516 #define	EVAL_OP_BIN_PROTECT4(op, name)				\
1517 		EVAL_OP_BIN_PROTECT_PROTO(op, name, INVD, E)	\
1518 		EVAL_OP_BIN_PROTECT_PROTO(op, name, INVD, D)	\
1519 		EVAL_OP_BIN_PROTECT_PROTO(op, name, INVD, R)	\
1520 		EVAL_OP_BIN_PROTECT_PROTO(op, name, INVD, INVD)
1521 
1522 	expr = ADDR(expr_place);
1523 
1524 	switch (expr->type) {
1525 	case ITM_EXPR_NONE:		/* not used */
1526 		return (0);
1527 	case ITM_EXPR_NOP:		/* not used */
1528 		return (0);
1529 	case ITM_EXPR_NAME:		/* not used */
1530 		return (0);
1531 	case ITM_EXPR_INT:		/* integer */
1532 		return (expr->data.itm_exnum);
1533 	case ITM_EXPR_SEQ:		/* byte sequence */
1534 		if ((sizeof (itm_place_t)) < expr->data.value.size) {
1535 			p = (unsigned char *)ADDR(expr->data.value.place);
1536 		} else {
1537 			p = (unsigned char *)&(expr->data.value.place);
1538 		}
1539 		for (i = 0, num = 0; i < expr->data.value.size; i++, p++) {
1540 			num = ((num << 8) | *p);
1541 		}
1542 		return	(num);
1543 	case ITM_EXPR_REG:		/* register */
1544 		return (REG(expr->data.itm_exnum));
1545 	case ITM_EXPR_IN_VECTOR:	/* in[expr] */
1546 		num = EVAL_EXPR(0);
1547 		if ((0 <= num) && (num < inbytesleft)) {
1548 			return (*((unsigned char *)(inbuf + num)));
1549 		} else if ((-1) == num) {
1550 			return	(inbytesleft);
1551 		} else {
1552 			return (0);
1553 		}
1554 	case ITM_EXPR_IN_VECTOR_D:	/* in[DECIMAL] */
1555 		num = expr->data.itm_exnum;
1556 		if ((0 <= num) && (num < inbytesleft)) {
1557 			return (*((unsigned char *)(inbuf + num)));
1558 		} else if ((-1) == num) {
1559 			return	(inbytesleft);
1560 		} else {
1561 			return (0);
1562 		}
1563 	case ITM_EXPR_OUT:		/* out */
1564 		return	(outbytesleft);
1565 	case ITM_EXPR_TRUE:		/* true */
1566 		return (1);
1567 	case ITM_EXPR_FALSE:		/* false */
1568 		return (0);
1569 	case ITM_EXPR_UMINUS:		/* unary minus */
1570 		return ((-1) * EVAL_EXPR(0));
1571 #define	PLUS_FOR_CSTYLE_CLEAN +
1572 #define	MINUS_FOR_CSTYLE_CLEAN -
1573 #define	MUL_FOR_CSTYLE_CLEAN *
1574 #define	DIV_FOR_CSTYLE_CLEAN /
1575 #define	MOD_FOR_CSTYLE_CLEAN %
1576 #define	SHIFT_L_FOR_CSTYLE_CLEAN <<
1577 #define	SHIFT_R_FOR_CSTYLE_CLEAN >>
1578 #define	OR_FOR_CSTYLE_CLEAN |
1579 #define	XOR_FOR_CSTYLE_CLEAN ^
1580 #define	AND_FOR_CSTYLE_CLEAN &
1581 #define	EQ_FOR_CSTYLE_CLEAN ==
1582 #define	NE_FOR_CSTYLE_CLEAN !=
1583 #define	GT_FOR_CSTYLE_CLEAN >
1584 #define	GE_FOR_CSTYLE_CLEAN >=
1585 #define	LT_FOR_CSTYLE_CLEAN <
1586 #define	LE_FOR_CSTYLE_CLEAN <=
1587 	EVAL_OP_BIN1(PLUS_FOR_CSTYLE_CLEAN, PLUS)	/* A + B */
1588 	EVAL_OP_BIN2(PLUS_FOR_CSTYLE_CLEAN, PLUS)	/* A + B */
1589 	EVAL_OP_BIN3(PLUS_FOR_CSTYLE_CLEAN, PLUS)	/* A + B */
1590 	EVAL_OP_BIN4(PLUS_FOR_CSTYLE_CLEAN, PLUS)	/* A + B */
1591 
1592 	EVAL_OP_BIN1(MINUS_FOR_CSTYLE_CLEAN, MINUS)	/* A - B */
1593 	EVAL_OP_BIN2(MINUS_FOR_CSTYLE_CLEAN, MINUS)	/* A - B */
1594 	EVAL_OP_BIN3(MINUS_FOR_CSTYLE_CLEAN, MINUS)	/* A - B */
1595 	EVAL_OP_BIN4(MINUS_FOR_CSTYLE_CLEAN, MINUS)	/* A - B */
1596 
1597 	EVAL_OP_BIN1(MUL_FOR_CSTYLE_CLEAN, MUL)		/* A * B */
1598 	EVAL_OP_BIN2(MUL_FOR_CSTYLE_CLEAN, MUL)		/* A * B */
1599 	EVAL_OP_BIN3(MUL_FOR_CSTYLE_CLEAN, MUL)		/* A * B */
1600 	EVAL_OP_BIN4(MUL_FOR_CSTYLE_CLEAN, MUL)		/* A * B */
1601 
1602 	EVAL_OP_BIN_PROTECT1(DIV_FOR_CSTYLE_CLEAN, DIV)	/* A / B */
1603 	EVAL_OP_BIN_PROTECT2(DIV_FOR_CSTYLE_CLEAN, DIV)	/* A / B */
1604 	EVAL_OP_BIN_PROTECT3(DIV_FOR_CSTYLE_CLEAN, DIV)	/* A / B */
1605 	EVAL_OP_BIN_PROTECT4(DIV_FOR_CSTYLE_CLEAN, DIV)	/* A / B */
1606 
1607 	EVAL_OP_BIN_PROTECT1(MOD_FOR_CSTYLE_CLEAN, MOD)	/* A % B */
1608 	EVAL_OP_BIN_PROTECT2(MOD_FOR_CSTYLE_CLEAN, MOD)	/* A % B */
1609 	EVAL_OP_BIN_PROTECT3(MOD_FOR_CSTYLE_CLEAN, MOD)	/* A % B */
1610 	EVAL_OP_BIN_PROTECT4(MOD_FOR_CSTYLE_CLEAN, MOD)	/* A % B */
1611 
1612 	EVAL_OP_BIN1(SHIFT_L_FOR_CSTYLE_CLEAN, SHIFT_L)	/* A << B */
1613 	EVAL_OP_BIN2(SHIFT_L_FOR_CSTYLE_CLEAN, SHIFT_L)	/* A << B */
1614 	EVAL_OP_BIN3(SHIFT_L_FOR_CSTYLE_CLEAN, SHIFT_L)	/* A << B */
1615 	EVAL_OP_BIN4(SHIFT_L_FOR_CSTYLE_CLEAN, SHIFT_L)	/* A << B */
1616 
1617 	EVAL_OP_BIN1(SHIFT_R_FOR_CSTYLE_CLEAN, SHIFT_R)	/* A >> B */
1618 	EVAL_OP_BIN2(SHIFT_R_FOR_CSTYLE_CLEAN, SHIFT_R)	/* A >> B */
1619 	EVAL_OP_BIN3(SHIFT_R_FOR_CSTYLE_CLEAN, SHIFT_R)	/* A >> B */
1620 	EVAL_OP_BIN4(SHIFT_R_FOR_CSTYLE_CLEAN, SHIFT_R)	/* A >> B */
1621 
1622 	EVAL_OP_BIN1(OR_FOR_CSTYLE_CLEAN, OR)		/* A |	B */
1623 	EVAL_OP_BIN2(OR_FOR_CSTYLE_CLEAN, OR)		/* A |	B */
1624 	EVAL_OP_BIN3(OR_FOR_CSTYLE_CLEAN, OR)		/* A |	B */
1625 	EVAL_OP_BIN4(OR_FOR_CSTYLE_CLEAN, OR)		/* A |	B */
1626 
1627 	EVAL_OP_BIN1(XOR_FOR_CSTYLE_CLEAN, XOR)		/* A ^	B */
1628 	EVAL_OP_BIN2(XOR_FOR_CSTYLE_CLEAN, XOR)		/* A ^	B */
1629 	EVAL_OP_BIN3(XOR_FOR_CSTYLE_CLEAN, XOR)		/* A ^	B */
1630 	EVAL_OP_BIN4(XOR_FOR_CSTYLE_CLEAN, XOR)		/* A ^	B */
1631 
1632 	EVAL_OP_BIN1(AND_FOR_CSTYLE_CLEAN, AND)		/* A &	B */
1633 	EVAL_OP_BIN2(AND_FOR_CSTYLE_CLEAN, AND)		/* A &	B */
1634 	EVAL_OP_BIN3(AND_FOR_CSTYLE_CLEAN, AND)		/* A &	B */
1635 	EVAL_OP_BIN4(AND_FOR_CSTYLE_CLEAN, AND)		/* A &	B */
1636 
1637 	EVAL_OP_BIN1(EQ_FOR_CSTYLE_CLEAN, EQ)		/* A == B */
1638 	EVAL_OP_BIN2(EQ_FOR_CSTYLE_CLEAN, EQ)		/* A == B */
1639 	EVAL_OP_BIN3(EQ_FOR_CSTYLE_CLEAN, EQ)		/* A == B */
1640 	EVAL_OP_BIN4(EQ_FOR_CSTYLE_CLEAN, EQ)		/* A == B */
1641 
1642 	EVAL_OP_BIN1(NE_FOR_CSTYLE_CLEAN, NE)		/* A != B */
1643 	EVAL_OP_BIN2(NE_FOR_CSTYLE_CLEAN, NE)		/* A != B */
1644 	EVAL_OP_BIN3(NE_FOR_CSTYLE_CLEAN, NE)		/* A != B */
1645 	EVAL_OP_BIN4(NE_FOR_CSTYLE_CLEAN, NE)		/* A != B */
1646 
1647 	EVAL_OP_BIN1(GT_FOR_CSTYLE_CLEAN, GT)		/* A >	B */
1648 	EVAL_OP_BIN2(GT_FOR_CSTYLE_CLEAN, GT)		/* A >	B */
1649 	EVAL_OP_BIN3(GT_FOR_CSTYLE_CLEAN, GT)		/* A >	B */
1650 	EVAL_OP_BIN4(GT_FOR_CSTYLE_CLEAN, GT)		/* A >	B */
1651 
1652 	EVAL_OP_BIN1(GE_FOR_CSTYLE_CLEAN, GE)		/* A >= B */
1653 	EVAL_OP_BIN2(GE_FOR_CSTYLE_CLEAN, GE)		/* A >= B */
1654 	EVAL_OP_BIN3(GE_FOR_CSTYLE_CLEAN, GE)		/* A >= B */
1655 	EVAL_OP_BIN4(GE_FOR_CSTYLE_CLEAN, GE)		/* A >= B */
1656 
1657 	EVAL_OP_BIN1(LT_FOR_CSTYLE_CLEAN, LT)		/* A <	B */
1658 	EVAL_OP_BIN2(LT_FOR_CSTYLE_CLEAN, LT)		/* A <	B */
1659 	EVAL_OP_BIN3(LT_FOR_CSTYLE_CLEAN, LT)		/* A <	B */
1660 	EVAL_OP_BIN4(LT_FOR_CSTYLE_CLEAN, LT)		/* A <	B */
1661 
1662 	EVAL_OP_BIN1(LE_FOR_CSTYLE_CLEAN, LE)		/* A <= B */
1663 	EVAL_OP_BIN2(LE_FOR_CSTYLE_CLEAN, LE)		/* A <= B */
1664 	EVAL_OP_BIN3(LE_FOR_CSTYLE_CLEAN, LE)		/* A <= B */
1665 	EVAL_OP_BIN4(LE_FOR_CSTYLE_CLEAN, LE)		/* A <= B */
1666 
1667 	case ITM_EXPR_NOT:		/*   !A	  */
1668 		return (!(EVAL_EXPR(0)));
1669 	case ITM_EXPR_NEG:		/*   ~A	  */
1670 		return (~(EVAL_EXPR(0)));
1671 	case ITM_EXPR_LOR:		/* A || B */
1672 		if (0 != (num = EVAL_EXPR(0)))
1673 			return	(num);
1674 		if (0 != (num = EVAL_EXPR(1)))
1675 			return	(num);
1676 		return (0);
1677 	case ITM_EXPR_LAND:		/* A && B */
1678 		if (0 == EVAL_EXPR(0))
1679 			return (0);
1680 		if (0 == (num = EVAL_EXPR(1)))
1681 			return (0);
1682 		return	(num);
1683 	case ITM_EXPR_ASSIGN:		/* A  = B */
1684 		num = EVAL_EXPR(1);
1685 		if (expr->data.operand[0].itm_ptr < ist->itm_hdr->reg_num) {
1686 			return (*(ist->regs + expr->data.operand[0].itm_ptr)
1687 			    = num);
1688 		} else {
1689 			return (0);
1690 		}
1691 	case ITM_EXPR_IN_EQ:		/* in == A */
1692 		expr_op = ADDR(expr->data.operand[0]);
1693 		switch (expr_op->type) {
1694 		case ITM_EXPR_SEQ:
1695 			if (inbytesleft < expr_op->data.value.size) {
1696 				return (0);
1697 			}
1698 			p = DADDR(&(expr_op->data.value));
1699 			for (i = 0; i < expr_op->data.value.size; i++, p++) {
1700 				if (*p != *(inbuf + i)) {
1701 					return (0);
1702 				}
1703 			}
1704 			return (1);
1705 		default:
1706 			num = EVAL_EXPR(0);
1707 			return (num == *((unsigned char *)inbuf));
1708 		}
1709 	default:
1710 		break;
1711 	}
1712 
1713 	return (0);
1714 
1715 #undef EVAL_EXPR_E
1716 #undef EVAL_EXPR_D
1717 #undef EVAL_EXPR_R
1718 #undef EVAL_EXPR_INVD
1719 #undef EVAL_EXPR
1720 }
1721 
1722 
1723 /*
1724  * maintain ITM reference information
1725  */
1726 static void
itm_ref_free(int fd,void * ptr0,void * ptr1,void * ptr2,size_t len)1727 itm_ref_free(int fd, void *ptr0, void *ptr1, void *ptr2, size_t len)
1728 {
1729 	int	r;
1730 	r = errno;
1731 	if (0 <= fd) {
1732 		(void) close(fd);
1733 	}
1734 	free(ptr0);
1735 	free(ptr1);
1736 	if (0 < len) {
1737 		(void) munmap(ptr2, len);
1738 	}
1739 	errno = r;
1740 }
1741 
1742 static itm_ref_t *
itm_ref_inc(const char * itm)1743 itm_ref_inc(const char		*itm)
1744 {
1745 	itm_ref_t	*ref;
1746 	itm_hdr_t	*hdr;
1747 	struct stat	st;
1748 	int		fd;
1749 
1750 	fd = open(itm, O_RDONLY, 0);
1751 	if (fd == -1) {
1752 		itm_ref_free(-1, NULL, NULL, NULL, 0);
1753 		return	(NULL);
1754 	}
1755 
1756 	if (fstat(fd, &st) == -1) {
1757 		itm_ref_free(fd, NULL, NULL, NULL, 0);
1758 		return	(NULL);
1759 	}
1760 	hdr = (void *) mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
1761 	if (MAP_FAILED == hdr) {
1762 		itm_ref_free(fd, NULL, NULL, NULL, 0);
1763 		return	(NULL);
1764 	}
1765 
1766 	(void) close(fd);
1767 
1768 	ref = malloc(sizeof (itm_ref_t));
1769 	if (NULL == ref) {
1770 		itm_ref_free(-1, NULL, NULL, hdr, st.st_size);
1771 		return	(NULL);
1772 	}
1773 	ref->name = malloc(strlen(itm) + 1);
1774 	if (NULL == ref->name) {
1775 		itm_ref_free(-1, ref, NULL, hdr, st.st_size);
1776 		return	(NULL);
1777 	}
1778 	(void) strcpy(ref->name, itm);
1779 	ref->hdr = hdr;
1780 	ref->len = st.st_size;
1781 
1782 	if ((hdr->ident[0] != ITM_IDENT_0) ||
1783 	    (hdr->ident[1] != ITM_IDENT_1) ||
1784 	    (hdr->ident[2] != ITM_IDENT_2) ||
1785 	    (hdr->ident[3] != ITM_IDENT_3) ||
1786 	    (hdr->spec[0] != ITM_SPEC_0) ||
1787 	    (hdr->spec[1] != ITM_SPEC_1) ||
1788 	    (hdr->spec[2] != ITM_SPEC_2) ||
1789 #if defined(_LITTLE_ENDIAN)
1790 #if defined(_LP64)
1791 	    ((hdr->spec[3] != ITM_SPEC_3_32_LITTLE_ENDIAN) &&
1792 	    (hdr->spec[3] != ITM_SPEC_3_64_LITTLE_ENDIAN)) ||
1793 #else
1794 	    (hdr->spec[3] != ITM_SPEC_3_32_LITTLE_ENDIAN) ||
1795 #endif
1796 #else
1797 #if defined(_LP64)
1798 	    ((hdr->spec[3] != ITM_SPEC_3_32_BIG_ENDIAN) &&
1799 	    (hdr->spec[3] != ITM_SPEC_3_64_BIG_ENDIAN)) ||
1800 #else
1801 	    (hdr->spec[3] != ITM_SPEC_3_32_BIG_ENDIAN) ||
1802 #endif
1803 #endif
1804 	    (hdr->version[0] != ITM_VER_0) ||
1805 	    (hdr->version[1] != ITM_VER_1) ||
1806 	    (hdr->version[2] != ITM_VER_2) ||
1807 	    (hdr->version[3] != ITM_VER_3) ||
1808 	    (((size_t)(hdr->itm_size.itm_ptr)) != st.st_size)) {
1809 		itm_ref_free(-1, ref, ref->name, ref->hdr, ref->len);
1810 		errno = ELIBBAD;
1811 		TRACE_MESSAGE('e', ("itm_ref_inc:error=%d\n", errno));
1812 		return	(NULL);
1813 	}
1814 
1815 	return	(ref);
1816 }
1817 
1818 
1819 static void
itm_ref_dec(itm_ref_t * ref)1820 itm_ref_dec(itm_ref_t	*ref)
1821 {
1822 	(void) munmap((char *)(ref->hdr), ref->len);
1823 	free(ref->name);
1824 	free(ref);
1825 }
1826 
1827 
1828 static void
op_init_default(icv_state_t * ist)1829 op_init_default(icv_state_t	*ist)
1830 {
1831 	ist->direc = ADDR(ist->itm_hdr->direc_init_tbl);
1832 	regs_init(ist);
1833 }
1834 
1835 
1836 static void
op_reset_default(icv_state_t * ist)1837 op_reset_default(icv_state_t	*ist)
1838 {
1839 	ist->direc = ADDR(ist->itm_hdr->direc_init_tbl);
1840 	regs_init(ist);
1841 }
1842 
1843 
1844 static void
regs_init(icv_state_t * ist)1845 regs_init(icv_state_t	*ist)
1846 {
1847 	if (0 < ist->itm_hdr->reg_num) {
1848 		(void) memset(ist->regs, 0,
1849 		    (sizeof (itm_num_t)) * ist->itm_hdr->reg_num);
1850 	}
1851 }
1852 
1853 
1854 #if defined(DEBUG)
1855 static void
trace_init()1856 trace_init()
1857 {
1858 	char	*env_val;
1859 	char	*p;
1860 
1861 	env_val = getenv("ITM_INT_TRACE");
1862 	if (NULL == env_val)
1863 		return;
1864 
1865 	for (p = env_val; *p; p++) {
1866 		trace_option[(*p) & 0x007f] = 1;
1867 	}
1868 }
1869 
1870 static void
trace_message(char * format,...)1871 trace_message(char	*format, ...)
1872 {
1873 	va_list	ap;
1874 
1875 	va_start(ap, format);
1876 
1877 	(void) vfprintf(stderr, format, ap);
1878 
1879 	va_end(ap);
1880 }
1881 #endif /* DEBUG */
1882