Fix filter: fix stack leak on taken branch
[lttng-ust.git] / liblttng-ust / lttng-filter-interpreter.c
CommitLineData
97b58163
MD
1/*
2 * lttng-filter-interpreter.c
3 *
4 * LTTng UST filter interpreter.
5 *
6 * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; only
11 * version 2.1 of the License.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23#include "lttng-filter.h"
24
25/*
26 * -1: wildcard found.
27 * -2: unknown escape char.
28 * 0: normal char.
29 */
30
31static
32int parse_char(const char **p)
33{
34 switch (**p) {
35 case '\\':
36 (*p)++;
37 switch (**p) {
38 case '\\':
39 case '*':
40 return 0;
41 default:
42 return -2;
43 }
44 case '*':
45 return -1;
46 default:
47 return 0;
48 }
49}
50
51static
0305960f 52int stack_strcmp(struct estack *stack, const char *cmp_type)
97b58163 53{
0305960f 54 const char *p = estack_bx(stack)->u.s.str, *q = estack_ax(stack)->u.s.str;
97b58163
MD
55 int ret;
56 int diff;
57
58 for (;;) {
59 int escaped_r0 = 0;
60
0305960f
MD
61 if (unlikely(p - estack_bx(stack)->u.s.str > estack_bx(stack)->u.s.seq_len || *p == '\0')) {
62 if (q - estack_ax(stack)->u.s.str > estack_ax(stack)->u.s.seq_len || *q == '\0')
97b58163
MD
63 diff = 0;
64 else
65 diff = -1;
66 break;
67 }
0305960f
MD
68 if (unlikely(q - estack_ax(stack)->u.s.str > estack_ax(stack)->u.s.seq_len || *q == '\0')) {
69 if (p - estack_bx(stack)->u.s.str > estack_bx(stack)->u.s.seq_len || *p == '\0')
97b58163
MD
70 diff = 0;
71 else
72 diff = 1;
73 break;
74 }
0305960f 75 if (estack_bx(stack)->u.s.literal) {
97b58163
MD
76 ret = parse_char(&p);
77 if (ret == -1) {
78 return 0;
79 } else if (ret == -2) {
80 escaped_r0 = 1;
81 }
82 /* else compare both char */
83 }
0305960f 84 if (estack_ax(stack)->u.s.literal) {
97b58163
MD
85 ret = parse_char(&q);
86 if (ret == -1) {
87 return 0;
88 } else if (ret == -2) {
89 if (!escaped_r0)
90 return -1;
91 } else {
92 if (escaped_r0)
93 return 1;
94 }
95 } else {
96 if (escaped_r0)
97 return 1;
98 }
99 diff = *p - *q;
100 if (diff != 0)
101 break;
102 p++;
103 q++;
104 }
105 return diff;
106}
107
108int lttng_filter_false(void *filter_data,
109 const char *filter_stack_data)
110{
111 return 0;
112}
113
114#ifdef INTERPRETER_USE_SWITCH
115
116/*
117 * Fallback for compilers that do not support taking address of labels.
118 */
119
120#define START_OP \
121 start_pc = &bytecode->data[0]; \
122 for (pc = next_pc = start_pc; pc - start_pc < bytecode->len; \
123 pc = next_pc) { \
124 dbg_printf("Executing op %s (%u)\n", \
125 print_op((unsigned int) *(filter_opcode_t *) pc), \
126 (unsigned int) *(filter_opcode_t *) pc); \
127 switch (*(filter_opcode_t *) pc) {
128
129#define OP(name) case name
130
131#define PO break
132
133#define END_OP } \
134 }
135
136#else
137
138/*
139 * Dispatch-table based interpreter.
140 */
141
142#define START_OP \
143 start_pc = &bytecode->data[0]; \
144 pc = next_pc = start_pc; \
145 if (unlikely(pc - start_pc >= bytecode->len)) \
146 goto end; \
147 goto *dispatch[*(filter_opcode_t *) pc];
148
149#define OP(name) \
150LABEL_##name
151
152#define PO \
153 pc = next_pc; \
154 goto *dispatch[*(filter_opcode_t *) pc];
155
156#define END_OP
157
158#endif
159
160int lttng_filter_interpret_bytecode(void *filter_data,
161 const char *filter_stack_data)
162{
163 struct bytecode_runtime *bytecode = filter_data;
164 void *pc, *next_pc, *start_pc;
165 int ret = -EINVAL;
166 int retval = 0;
0305960f
MD
167 struct estack _stack;
168 struct estack *stack = &_stack;
97b58163
MD
169#ifndef INTERPRETER_USE_SWITCH
170 static void *dispatch[NR_FILTER_OPS] = {
171 [ FILTER_OP_UNKNOWN ] = &&LABEL_FILTER_OP_UNKNOWN,
172
173 [ FILTER_OP_RETURN ] = &&LABEL_FILTER_OP_RETURN,
174
175 /* binary */
176 [ FILTER_OP_MUL ] = &&LABEL_FILTER_OP_MUL,
177 [ FILTER_OP_DIV ] = &&LABEL_FILTER_OP_DIV,
178 [ FILTER_OP_MOD ] = &&LABEL_FILTER_OP_MOD,
179 [ FILTER_OP_PLUS ] = &&LABEL_FILTER_OP_PLUS,
180 [ FILTER_OP_MINUS ] = &&LABEL_FILTER_OP_MINUS,
181 [ FILTER_OP_RSHIFT ] = &&LABEL_FILTER_OP_RSHIFT,
182 [ FILTER_OP_LSHIFT ] = &&LABEL_FILTER_OP_LSHIFT,
183 [ FILTER_OP_BIN_AND ] = &&LABEL_FILTER_OP_BIN_AND,
184 [ FILTER_OP_BIN_OR ] = &&LABEL_FILTER_OP_BIN_OR,
185 [ FILTER_OP_BIN_XOR ] = &&LABEL_FILTER_OP_BIN_XOR,
186
187 /* binary comparators */
188 [ FILTER_OP_EQ ] = &&LABEL_FILTER_OP_EQ,
189 [ FILTER_OP_NE ] = &&LABEL_FILTER_OP_NE,
190 [ FILTER_OP_GT ] = &&LABEL_FILTER_OP_GT,
191 [ FILTER_OP_LT ] = &&LABEL_FILTER_OP_LT,
192 [ FILTER_OP_GE ] = &&LABEL_FILTER_OP_GE,
193 [ FILTER_OP_LE ] = &&LABEL_FILTER_OP_LE,
194
195 /* string binary comparator */
196 [ FILTER_OP_EQ_STRING ] = &&LABEL_FILTER_OP_EQ_STRING,
197 [ FILTER_OP_NE_STRING ] = &&LABEL_FILTER_OP_NE_STRING,
198 [ FILTER_OP_GT_STRING ] = &&LABEL_FILTER_OP_GT_STRING,
199 [ FILTER_OP_LT_STRING ] = &&LABEL_FILTER_OP_LT_STRING,
200 [ FILTER_OP_GE_STRING ] = &&LABEL_FILTER_OP_GE_STRING,
201 [ FILTER_OP_LE_STRING ] = &&LABEL_FILTER_OP_LE_STRING,
202
203 /* s64 binary comparator */
204 [ FILTER_OP_EQ_S64 ] = &&LABEL_FILTER_OP_EQ_S64,
205 [ FILTER_OP_NE_S64 ] = &&LABEL_FILTER_OP_NE_S64,
206 [ FILTER_OP_GT_S64 ] = &&LABEL_FILTER_OP_GT_S64,
207 [ FILTER_OP_LT_S64 ] = &&LABEL_FILTER_OP_LT_S64,
208 [ FILTER_OP_GE_S64 ] = &&LABEL_FILTER_OP_GE_S64,
209 [ FILTER_OP_LE_S64 ] = &&LABEL_FILTER_OP_LE_S64,
210
211 /* double binary comparator */
212 [ FILTER_OP_EQ_DOUBLE ] = &&LABEL_FILTER_OP_EQ_DOUBLE,
213 [ FILTER_OP_NE_DOUBLE ] = &&LABEL_FILTER_OP_NE_DOUBLE,
214 [ FILTER_OP_GT_DOUBLE ] = &&LABEL_FILTER_OP_GT_DOUBLE,
215 [ FILTER_OP_LT_DOUBLE ] = &&LABEL_FILTER_OP_LT_DOUBLE,
216 [ FILTER_OP_GE_DOUBLE ] = &&LABEL_FILTER_OP_GE_DOUBLE,
217 [ FILTER_OP_LE_DOUBLE ] = &&LABEL_FILTER_OP_LE_DOUBLE,
218
219 /* unary */
220 [ FILTER_OP_UNARY_PLUS ] = &&LABEL_FILTER_OP_UNARY_PLUS,
221 [ FILTER_OP_UNARY_MINUS ] = &&LABEL_FILTER_OP_UNARY_MINUS,
222 [ FILTER_OP_UNARY_NOT ] = &&LABEL_FILTER_OP_UNARY_NOT,
223 [ FILTER_OP_UNARY_PLUS_S64 ] = &&LABEL_FILTER_OP_UNARY_PLUS_S64,
224 [ FILTER_OP_UNARY_MINUS_S64 ] = &&LABEL_FILTER_OP_UNARY_MINUS_S64,
225 [ FILTER_OP_UNARY_NOT_S64 ] = &&LABEL_FILTER_OP_UNARY_NOT_S64,
226 [ FILTER_OP_UNARY_PLUS_DOUBLE ] = &&LABEL_FILTER_OP_UNARY_PLUS_DOUBLE,
227 [ FILTER_OP_UNARY_MINUS_DOUBLE ] = &&LABEL_FILTER_OP_UNARY_MINUS_DOUBLE,
228 [ FILTER_OP_UNARY_NOT_DOUBLE ] = &&LABEL_FILTER_OP_UNARY_NOT_DOUBLE,
229
230 /* logical */
231 [ FILTER_OP_AND ] = &&LABEL_FILTER_OP_AND,
232 [ FILTER_OP_OR ] = &&LABEL_FILTER_OP_OR,
233
234 /* load */
235 [ FILTER_OP_LOAD_FIELD_REF ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF,
236 [ FILTER_OP_LOAD_FIELD_REF_STRING ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_STRING,
237 [ FILTER_OP_LOAD_FIELD_REF_SEQUENCE ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_SEQUENCE,
238 [ FILTER_OP_LOAD_FIELD_REF_S64 ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_S64,
239 [ FILTER_OP_LOAD_FIELD_REF_DOUBLE ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_DOUBLE,
240
241 [ FILTER_OP_LOAD_STRING ] = &&LABEL_FILTER_OP_LOAD_STRING,
242 [ FILTER_OP_LOAD_S64 ] = &&LABEL_FILTER_OP_LOAD_S64,
243 [ FILTER_OP_LOAD_DOUBLE ] = &&LABEL_FILTER_OP_LOAD_DOUBLE,
244
245 /* cast */
246 [ FILTER_OP_CAST_TO_S64 ] = &&LABEL_FILTER_OP_CAST_TO_S64,
247 [ FILTER_OP_CAST_DOUBLE_TO_S64 ] = &&LABEL_FILTER_OP_CAST_DOUBLE_TO_S64,
248 [ FILTER_OP_CAST_NOP ] = &&LABEL_FILTER_OP_CAST_NOP,
249 };
250#endif /* #ifndef INTERPRETER_USE_SWITCH */
251
0305960f
MD
252 estack_init(stack);
253
97b58163
MD
254 START_OP
255
256 OP(FILTER_OP_UNKNOWN):
257 OP(FILTER_OP_LOAD_FIELD_REF):
258#ifdef INTERPRETER_USE_SWITCH
259 default:
260#endif /* INTERPRETER_USE_SWITCH */
261 ERR("unknown bytecode op %u\n",
262 (unsigned int) *(filter_opcode_t *) pc);
263 ret = -EINVAL;
264 goto end;
265
266 OP(FILTER_OP_RETURN):
0305960f 267 retval = !!estack_ax(stack)->u.v;
97b58163
MD
268 ret = 0;
269 goto end;
270
271 /* binary */
272 OP(FILTER_OP_MUL):
273 OP(FILTER_OP_DIV):
274 OP(FILTER_OP_MOD):
275 OP(FILTER_OP_PLUS):
276 OP(FILTER_OP_MINUS):
277 OP(FILTER_OP_RSHIFT):
278 OP(FILTER_OP_LSHIFT):
279 OP(FILTER_OP_BIN_AND):
280 OP(FILTER_OP_BIN_OR):
281 OP(FILTER_OP_BIN_XOR):
282 ERR("unsupported bytecode op %u\n",
283 (unsigned int) *(filter_opcode_t *) pc);
284 ret = -EINVAL;
285 goto end;
286
287 OP(FILTER_OP_EQ):
288 OP(FILTER_OP_NE):
289 OP(FILTER_OP_GT):
290 OP(FILTER_OP_LT):
291 OP(FILTER_OP_GE):
292 OP(FILTER_OP_LE):
293 ERR("unsupported non-specialized bytecode op %u\n",
294 (unsigned int) *(filter_opcode_t *) pc);
295 ret = -EINVAL;
296 goto end;
297
298 OP(FILTER_OP_EQ_STRING):
299 {
0305960f
MD
300 int res;
301
302 res = (stack_strcmp(stack, "==") == 0);
303 estack_pop(stack);
304 estack_ax(stack)->u.v = res;
305 estack_ax(stack)->type = REG_S64;
97b58163
MD
306 next_pc += sizeof(struct binary_op);
307 PO;
308 }
309 OP(FILTER_OP_NE_STRING):
310 {
0305960f
MD
311 int res;
312
313 res = (stack_strcmp(stack, "!=") != 0);
314 estack_pop(stack);
315 estack_ax(stack)->u.v = res;
316 estack_ax(stack)->type = REG_S64;
97b58163
MD
317 next_pc += sizeof(struct binary_op);
318 PO;
319 }
320 OP(FILTER_OP_GT_STRING):
321 {
0305960f
MD
322 int res;
323
324 res = (stack_strcmp(stack, ">") > 0);
325 estack_pop(stack);
326 estack_ax(stack)->u.v = res;
327 estack_ax(stack)->type = REG_S64;
97b58163
MD
328 next_pc += sizeof(struct binary_op);
329 PO;
330 }
331 OP(FILTER_OP_LT_STRING):
332 {
0305960f
MD
333 int res;
334
335 res = (stack_strcmp(stack, "<") < 0);
336 estack_pop(stack);
337 estack_ax(stack)->u.v = res;
338 estack_ax(stack)->type = REG_S64;
97b58163
MD
339 next_pc += sizeof(struct binary_op);
340 PO;
341 }
342 OP(FILTER_OP_GE_STRING):
343 {
0305960f
MD
344 int res;
345
346 res = (stack_strcmp(stack, ">=") >= 0);
347 estack_pop(stack);
348 estack_ax(stack)->u.v = res;
349 estack_ax(stack)->type = REG_S64;
97b58163
MD
350 next_pc += sizeof(struct binary_op);
351 PO;
352 }
353 OP(FILTER_OP_LE_STRING):
354 {
0305960f
MD
355 int res;
356
357 res = (stack_strcmp(stack, "<=") <= 0);
358 estack_pop(stack);
359 estack_ax(stack)->u.v = res;
360 estack_ax(stack)->type = REG_S64;
97b58163
MD
361 next_pc += sizeof(struct binary_op);
362 PO;
363 }
364
365 OP(FILTER_OP_EQ_S64):
366 {
0305960f
MD
367 int res;
368
369 res = (estack_bx(stack)->u.v == estack_ax(stack)->u.v);
370 estack_pop(stack);
371 estack_ax(stack)->u.v = res;
372 estack_ax(stack)->type = REG_S64;
97b58163
MD
373 next_pc += sizeof(struct binary_op);
374 PO;
375 }
376 OP(FILTER_OP_NE_S64):
377 {
0305960f
MD
378 int res;
379
380 res = (estack_bx(stack)->u.v != estack_ax(stack)->u.v);
381 estack_pop(stack);
382 estack_ax(stack)->u.v = res;
383 estack_ax(stack)->type = REG_S64;
97b58163
MD
384 next_pc += sizeof(struct binary_op);
385 PO;
386 }
387 OP(FILTER_OP_GT_S64):
388 {
0305960f
MD
389 int res;
390
391 res = (estack_bx(stack)->u.v > estack_ax(stack)->u.v);
392 estack_pop(stack);
393 estack_ax(stack)->u.v = res;
394 estack_ax(stack)->type = REG_S64;
97b58163
MD
395 next_pc += sizeof(struct binary_op);
396 PO;
397 }
398 OP(FILTER_OP_LT_S64):
399 {
0305960f
MD
400 int res;
401
402 res = (estack_bx(stack)->u.v < estack_ax(stack)->u.v);
403 estack_pop(stack);
404 estack_ax(stack)->u.v = res;
405 estack_ax(stack)->type = REG_S64;
97b58163
MD
406 next_pc += sizeof(struct binary_op);
407 PO;
408 }
409 OP(FILTER_OP_GE_S64):
410 {
0305960f
MD
411 int res;
412
413 res = (estack_bx(stack)->u.v >= estack_ax(stack)->u.v);
414 estack_pop(stack);
415 estack_ax(stack)->u.v = res;
416 estack_ax(stack)->type = REG_S64;
97b58163
MD
417 next_pc += sizeof(struct binary_op);
418 PO;
419 }
420 OP(FILTER_OP_LE_S64):
421 {
0305960f
MD
422 int res;
423
424 res = (estack_bx(stack)->u.v <= estack_ax(stack)->u.v);
425 estack_pop(stack);
426 estack_ax(stack)->u.v = res;
427 estack_ax(stack)->type = REG_S64;
97b58163
MD
428 next_pc += sizeof(struct binary_op);
429 PO;
430 }
431
432 OP(FILTER_OP_EQ_DOUBLE):
433 {
0305960f
MD
434 int res;
435
436 if (unlikely(estack_ax(stack)->type == REG_S64))
437 estack_ax(stack)->u.d = (double) estack_ax(stack)->u.v;
438 else if (unlikely(estack_bx(stack)->type == REG_S64))
439 estack_bx(stack)->u.d = (double) estack_bx(stack)->u.v;
440 res = (estack_bx(stack)->u.v == estack_ax(stack)->u.v);
441 estack_pop(stack);
442 estack_ax(stack)->u.v = res;
443 estack_ax(stack)->type = REG_S64;
97b58163
MD
444 next_pc += sizeof(struct binary_op);
445 PO;
446 }
447 OP(FILTER_OP_NE_DOUBLE):
448 {
0305960f
MD
449 int res;
450
451 if (unlikely(estack_ax(stack)->type == REG_S64))
452 estack_ax(stack)->u.d = (double) estack_ax(stack)->u.v;
453 else if (unlikely(estack_bx(stack)->type == REG_S64))
454 estack_bx(stack)->u.d = (double) estack_bx(stack)->u.v;
455 res = (estack_bx(stack)->u.v != estack_ax(stack)->u.v);
456 estack_pop(stack);
457 estack_ax(stack)->u.v = res;
458 estack_ax(stack)->type = REG_S64;
97b58163
MD
459 next_pc += sizeof(struct binary_op);
460 PO;
461 }
462 OP(FILTER_OP_GT_DOUBLE):
463 {
0305960f
MD
464 int res;
465
466 if (unlikely(estack_ax(stack)->type == REG_S64))
467 estack_ax(stack)->u.d = (double) estack_ax(stack)->u.v;
468 else if (unlikely(estack_bx(stack)->type == REG_S64))
469 estack_bx(stack)->u.d = (double) estack_bx(stack)->u.v;
470 res = (estack_bx(stack)->u.v > estack_ax(stack)->u.v);
471 estack_pop(stack);
472 estack_ax(stack)->u.v = res;
473 estack_ax(stack)->type = REG_S64;
97b58163
MD
474 next_pc += sizeof(struct binary_op);
475 PO;
476 }
477 OP(FILTER_OP_LT_DOUBLE):
478 {
0305960f
MD
479 int res;
480
481 if (unlikely(estack_ax(stack)->type == REG_S64))
482 estack_ax(stack)->u.d = (double) estack_ax(stack)->u.v;
483 else if (unlikely(estack_bx(stack)->type == REG_S64))
484 estack_bx(stack)->u.d = (double) estack_bx(stack)->u.v;
485 res = (estack_bx(stack)->u.v < estack_ax(stack)->u.v);
486 estack_pop(stack);
487 estack_ax(stack)->u.v = res;
488 estack_ax(stack)->type = REG_S64;
97b58163
MD
489 next_pc += sizeof(struct binary_op);
490 PO;
491 }
492 OP(FILTER_OP_GE_DOUBLE):
493 {
0305960f
MD
494 int res;
495
496 if (unlikely(estack_ax(stack)->type == REG_S64))
497 estack_ax(stack)->u.d = (double) estack_ax(stack)->u.v;
498 else if (unlikely(estack_bx(stack)->type == REG_S64))
499 estack_bx(stack)->u.d = (double) estack_bx(stack)->u.v;
500 res = (estack_bx(stack)->u.v >= estack_ax(stack)->u.v);
501 estack_pop(stack);
502 estack_ax(stack)->u.v = res;
503 estack_ax(stack)->type = REG_S64;
97b58163
MD
504 next_pc += sizeof(struct binary_op);
505 PO;
506 }
507 OP(FILTER_OP_LE_DOUBLE):
508 {
0305960f
MD
509 int res;
510
511 if (unlikely(estack_ax(stack)->type == REG_S64))
512 estack_ax(stack)->u.d = (double) estack_ax(stack)->u.v;
513 else if (unlikely(estack_bx(stack)->type == REG_S64))
514 estack_bx(stack)->u.d = (double) estack_bx(stack)->u.v;
515 res = (estack_bx(stack)->u.v <= estack_ax(stack)->u.v);
516 estack_pop(stack);
517 estack_ax(stack)->u.v = res;
518 estack_ax(stack)->type = REG_S64;
97b58163
MD
519 next_pc += sizeof(struct binary_op);
520 PO;
521 }
522
523 /* unary */
524 OP(FILTER_OP_UNARY_PLUS):
525 OP(FILTER_OP_UNARY_MINUS):
526 OP(FILTER_OP_UNARY_NOT):
527 ERR("unsupported non-specialized bytecode op %u\n",
528 (unsigned int) *(filter_opcode_t *) pc);
529 ret = -EINVAL;
530 goto end;
531
532
533 OP(FILTER_OP_UNARY_PLUS_S64):
534 OP(FILTER_OP_UNARY_PLUS_DOUBLE):
535 {
536 next_pc += sizeof(struct unary_op);
537 PO;
538 }
539 OP(FILTER_OP_UNARY_MINUS_S64):
540 {
0305960f 541 estack_ax(stack)->u.v = -estack_ax(stack)->u.v;
97b58163
MD
542 next_pc += sizeof(struct unary_op);
543 PO;
544 }
545 OP(FILTER_OP_UNARY_MINUS_DOUBLE):
546 {
0305960f 547 estack_ax(stack)->u.d = -estack_ax(stack)->u.d;
97b58163
MD
548 next_pc += sizeof(struct unary_op);
549 PO;
550 }
551 OP(FILTER_OP_UNARY_NOT_S64):
552 {
0305960f 553 estack_ax(stack)->u.v = !estack_ax(stack)->u.v;
97b58163
MD
554 next_pc += sizeof(struct unary_op);
555 PO;
556 }
557 OP(FILTER_OP_UNARY_NOT_DOUBLE):
558 {
0305960f 559 estack_ax(stack)->u.d = !estack_ax(stack)->u.d;
97b58163
MD
560 next_pc += sizeof(struct unary_op);
561 PO;
562 }
563
564 /* logical */
565 OP(FILTER_OP_AND):
566 {
567 struct logical_op *insn = (struct logical_op *) pc;
568
0305960f
MD
569 /* If AX is 0, skip and evaluate to 0 */
570 if (unlikely(estack_ax(stack)->u.v == 0)) {
97b58163
MD
571 dbg_printf("Jumping to bytecode offset %u\n",
572 (unsigned int) insn->skip_offset);
573 next_pc = start_pc + insn->skip_offset;
574 } else {
71c1ceeb
MD
575 /* Pop 1 when jump not taken */
576 estack_pop(stack);
97b58163
MD
577 next_pc += sizeof(struct logical_op);
578 }
579 PO;
580 }
581 OP(FILTER_OP_OR):
582 {
583 struct logical_op *insn = (struct logical_op *) pc;
584
0305960f 585 /* If AX is nonzero, skip and evaluate to 1 */
97b58163 586
0305960f
MD
587 if (unlikely(estack_ax(stack)->u.v != 0)) {
588 estack_ax(stack)->u.v = 1;
97b58163
MD
589 dbg_printf("Jumping to bytecode offset %u\n",
590 (unsigned int) insn->skip_offset);
591 next_pc = start_pc + insn->skip_offset;
592 } else {
71c1ceeb
MD
593 /* Pop 1 when jump not taken */
594 estack_pop(stack);
97b58163
MD
595 next_pc += sizeof(struct logical_op);
596 }
597 PO;
598 }
599
600
601 /* load */
602 OP(FILTER_OP_LOAD_FIELD_REF_STRING):
603 {
604 struct load_op *insn = (struct load_op *) pc;
605 struct field_ref *ref = (struct field_ref *) insn->data;
606
607 dbg_printf("load field ref offset %u type string\n",
608 ref->offset);
0305960f
MD
609 estack_push(stack);
610 estack_ax(stack)->u.s.str =
97b58163 611 *(const char * const *) &filter_stack_data[ref->offset];
0305960f 612 if (unlikely(!estack_ax(stack)->u.s.str)) {
97b58163
MD
613 dbg_printf("Filter warning: loading a NULL string.\n");
614 ret = -EINVAL;
615 goto end;
616 }
0305960f
MD
617 estack_ax(stack)->type = REG_STRING;
618 estack_ax(stack)->u.s.seq_len = UINT_MAX;
619 estack_ax(stack)->u.s.literal = 0;
620 dbg_printf("ref load string %s\n", estack_ax(stack)->u.s.str);
97b58163
MD
621 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
622 PO;
623 }
624
625 OP(FILTER_OP_LOAD_FIELD_REF_SEQUENCE):
626 {
627 struct load_op *insn = (struct load_op *) pc;
628 struct field_ref *ref = (struct field_ref *) insn->data;
629
630 dbg_printf("load field ref offset %u type sequence\n",
631 ref->offset);
0305960f
MD
632 estack_push(stack);
633 estack_ax(stack)->u.s.seq_len =
97b58163 634 *(unsigned long *) &filter_stack_data[ref->offset];
0305960f 635 estack_ax(stack)->u.s.str =
97b58163
MD
636 *(const char **) (&filter_stack_data[ref->offset
637 + sizeof(unsigned long)]);
0305960f 638 if (unlikely(!estack_ax(stack)->u.s.str)) {
97b58163
MD
639 dbg_printf("Filter warning: loading a NULL sequence.\n");
640 ret = -EINVAL;
641 goto end;
642 }
0305960f
MD
643 estack_ax(stack)->type = REG_STRING;
644 estack_ax(stack)->u.s.literal = 0;
97b58163
MD
645 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
646 PO;
647 }
648
649 OP(FILTER_OP_LOAD_FIELD_REF_S64):
650 {
651 struct load_op *insn = (struct load_op *) pc;
652 struct field_ref *ref = (struct field_ref *) insn->data;
653
654 dbg_printf("load field ref offset %u type s64\n",
655 ref->offset);
0305960f
MD
656 estack_push(stack);
657 memcpy(&estack_ax(stack)->u.v, &filter_stack_data[ref->offset],
97b58163 658 sizeof(struct literal_numeric));
0305960f
MD
659 estack_ax(stack)->type = REG_S64;
660 dbg_printf("ref load s64 %" PRIi64 "\n", estack_ax(stack)->u.v);
97b58163
MD
661 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
662 PO;
663 }
664
665 OP(FILTER_OP_LOAD_FIELD_REF_DOUBLE):
666 {
667 struct load_op *insn = (struct load_op *) pc;
668 struct field_ref *ref = (struct field_ref *) insn->data;
669
670 dbg_printf("load field ref offset %u type double\n",
671 ref->offset);
0305960f
MD
672 estack_push(stack);
673 memcpy(&estack_ax(stack)->u.d, &filter_stack_data[ref->offset],
97b58163 674 sizeof(struct literal_double));
0305960f
MD
675 estack_ax(stack)->type = REG_DOUBLE;
676 dbg_printf("ref load double %g\n", estack_ax(stack)->u.d);
97b58163
MD
677 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
678 PO;
679 }
680
681 OP(FILTER_OP_LOAD_STRING):
682 {
683 struct load_op *insn = (struct load_op *) pc;
684
685 dbg_printf("load string %s\n", insn->data);
0305960f
MD
686 estack_push(stack);
687 estack_ax(stack)->type = REG_STRING;
688 estack_ax(stack)->u.s.str = insn->data;
689 estack_ax(stack)->u.s.seq_len = UINT_MAX;
690 estack_ax(stack)->u.s.literal = 1;
97b58163
MD
691 next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
692 PO;
693 }
694
695 OP(FILTER_OP_LOAD_S64):
696 {
697 struct load_op *insn = (struct load_op *) pc;
698
0305960f
MD
699 estack_push(stack);
700 memcpy(&estack_ax(stack)->u.v, insn->data,
97b58163 701 sizeof(struct literal_numeric));
0305960f
MD
702 dbg_printf("load s64 %" PRIi64 "\n", estack_ax(stack)->u.v);
703 estack_ax(stack)->type = REG_S64;
97b58163
MD
704 next_pc += sizeof(struct load_op)
705 + sizeof(struct literal_numeric);
706 PO;
707 }
708
709 OP(FILTER_OP_LOAD_DOUBLE):
710 {
711 struct load_op *insn = (struct load_op *) pc;
712
0305960f
MD
713 estack_push(stack);
714 memcpy(&estack_ax(stack)->u.d, insn->data,
97b58163 715 sizeof(struct literal_double));
0305960f
MD
716 dbg_printf("load s64 %g\n", estack_ax(stack)->u.d);
717 estack_ax(stack)->type = REG_DOUBLE;
97b58163
MD
718 next_pc += sizeof(struct load_op)
719 + sizeof(struct literal_double);
720 PO;
721 }
722
723 /* cast */
724 OP(FILTER_OP_CAST_TO_S64):
725 ERR("unsupported non-specialized bytecode op %u\n",
726 (unsigned int) *(filter_opcode_t *) pc);
727 ret = -EINVAL;
728 goto end;
729
730 OP(FILTER_OP_CAST_DOUBLE_TO_S64):
731 {
0305960f
MD
732 estack_ax(stack)->u.v = (int64_t) estack_ax(stack)->u.d;
733 estack_ax(stack)->type = REG_S64;
97b58163
MD
734 next_pc += sizeof(struct cast_op);
735 PO;
736 }
737
738 OP(FILTER_OP_CAST_NOP):
739 {
740 next_pc += sizeof(struct cast_op);
741 PO;
742 }
743
744 END_OP
745end:
746 /* return 0 (discard) on error */
747 if (ret)
748 return 0;
749 return retval;
750}
751
752#undef START_OP
753#undef OP
754#undef PO
755#undef END_OP
This page took 0.052559 seconds and 4 git commands to generate.