1 /* GNU Mailutils -- a suite of utilities for electronic mail
2    Copyright (C) 1999-2021 Free Software Foundation, Inc.
3 
4    This library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 3 of the License, or (at your option) any later version.
8 
9    This library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
13 
14    You should have received a copy of the GNU Lesser General
15    Public License along with this library.  If not, see
16    <http://www.gnu.org/licenses/>. */
17 
18 #include <mailutils/sieve.h>
19 #include <mailutils/assoc.h>
20 #include <mailutils/locus.h>
21 #include <mailutils/yyloc.h>
22 #include <setjmp.h>
23 #include <string.h>
24 #include <regex.h>
25 
26 typedef void (*sieve_instr_t) (mu_sieve_machine_t mach);
27 
28 typedef union
29 {
30   sieve_instr_t instr;
31   mu_sieve_handler_t handler;
32   mu_sieve_value_t *val;
33   mu_sieve_comparator_t comp;
34   long number;
35   size_t pc;
36   size_t line;
37   int inum;
38   char *string;
39   unsigned unum;
40 } sieve_op_t;
41 
42 
43 #define MU_SV_SAVED_ERR_STATE 0x01
44 #define MU_SV_SAVED_DBG_STATE 0x02
45 #define MU_SV_SAVED_STATE     0x80
46 
47 enum mu_sieve_state
48   {
49     mu_sieve_state_init,
50     mu_sieve_state_error,
51     mu_sieve_state_compiled,
52     mu_sieve_state_running,
53     mu_sieve_state_disass
54   };
55 
56 struct mu_sieve_machine
57 {
58   /* Static data */
59   struct mu_locus_range locus; /* Approximate location in the code */
60   int changeloc:1;             /* If set during code generation phase, the
61 				  _mu_i_sv_instr_locus will be emitted before
62 				  next instruction */
63 
64   mu_list_t memory_pool;     /* Pool of allocated memory objects */
65   mu_list_t destr_list;      /* List of destructor functions */
66 
67   /* Symbol space: */
68   mu_opool_t string_pool;    /* String constants */
69   mu_list_t registry;        /* Tests, Actions, Comparators */
70 
71   char **idspace;            /* Source and identifier names */
72   size_t idcount;
73   size_t idmax;
74 
75   mu_sieve_string_t *stringspace;
76   size_t stringcount;
77   size_t stringmax;
78 
79   mu_sieve_value_t *valspace;
80   size_t valcount;
81   size_t valmax;
82 
83   size_t progsize;           /* Number of allocated program cells */
84   sieve_op_t *prog;          /* Compiled program */
85 
86   /* Runtime data */
87   enum mu_sieve_state state; /* Machine state */
88   size_t pc;                 /* Current program counter */
89   long reg;                  /* Numeric register */
90 
91   /* Support for variables (RFC 5229) */
92   mu_assoc_t vartab;         /* Table of variables */
93   char *match_string;        /* The string used in the most recent match */
94   regmatch_t *match_buf;     /* Offsets of parenthesized groups */
95   size_t match_count;        /* Actual number of elements used in match_buf */
96   size_t match_max;          /* Total number of elements available in match_buf */
97   mu_list_t init_var;        /* List of variable initializers */
98 
99   /* Call environment */
100   const char *identifier;    /* Name of action or test being executed */
101   size_t argstart;           /* Index of the first argument in valspace */
102   size_t argcount;           /* Number of positional arguments */
103   size_t tagcount;           /* Number of tagged arguments */
104   mu_sieve_comparator_t comparator; /* Comparator (for tests) */
105 
106   int dry_run;               /* Dry-run mode */
107   jmp_buf errbuf;            /* Target location for non-local exits */
108 
109   mu_assoc_t exenv;          /* Execution environment (RFC 5183) */
110 
111   mu_mailbox_t mailbox;      /* Mailbox to operate upon */
112   size_t    msgno;           /* Current message number */
113   mu_message_t msg;          /* Current message */
114   int action_count;          /* Number of actions executed over this message */
115 
116   /* Stream state info */
117   int state_flags;
118   int err_mode;
119   struct mu_locus_range err_locus;
120   int dbg_mode;
121   struct mu_locus_range dbg_locus;
122 
123   /* User supplied data */
124   mu_stream_t errstream;
125   mu_stream_t dbgstream;
126 
127   mu_sieve_action_log_t logger;
128 
129   mu_mailer_t mailer;
130   char *daemon_email;
131   void *data;
132 };
133 
134 enum mu_sieve_node_type
135   {
136     mu_sieve_node_noop,
137     mu_sieve_node_false,
138     mu_sieve_node_true,
139     mu_sieve_node_test,
140     mu_sieve_node_action,
141     mu_sieve_node_cond,
142     mu_sieve_node_anyof,
143     mu_sieve_node_allof,
144     mu_sieve_node_not,
145     mu_sieve_node_end,
146   };
147 
148 struct mu_sieve_node
149 {
150   struct mu_sieve_node *prev, *next;
151   enum mu_sieve_node_type type;
152   struct mu_locus_range locus;
153   union
154   {
155     struct mu_sieve_node *node;
156     struct
157     {
158       struct mu_sieve_node *expr;
159       struct mu_sieve_node *iftrue;
160       struct mu_sieve_node *iffalse;
161     } cond;
162     struct
163     {
164       mu_sieve_registry_t *reg;
165       size_t argstart;
166       size_t argcount;
167       size_t tagcount;
168       mu_sieve_comparator_t comparator; /* Comparator (for tests) */
169     } command;
170   } v;
171 };
172 
173 struct mu_sieve_node_list
174 {
175   struct mu_sieve_node *head, *tail;
176 };
177 
178 struct mu_sieve_variable_initializer
179 {
180   char *name;
181   char *value;
182 };
183 
184 int mu_sieve_yyerror (const char *s);
185 int mu_sieve_yylex (void);
186 
187 int mu_i_sv_lex_begin (const char *name);
188 int mu_i_sv_lex_begin_string (const char *buf, int bufsize,
189 			      struct mu_locus_point const *pt);
190 void mu_i_sv_lex_finish (void);
191 
192 extern mu_sieve_machine_t mu_sieve_machine;
193 
194 void mu_i_sv_code (struct mu_sieve_machine *mach, sieve_op_t op);
195 
196 int mu_i_sv_locus (struct mu_sieve_machine *mach, struct mu_locus_range *lr);
197 void mu_i_sv_code_action (struct mu_sieve_machine *mach,
198 			  struct mu_sieve_node *node);
199 void mu_i_sv_code_test (struct mu_sieve_machine *mach,
200 			struct mu_sieve_node *node);
201 
202 /* Opcodes */
203 void _mu_i_sv_instr_action (mu_sieve_machine_t mach);
204 void _mu_i_sv_instr_test (mu_sieve_machine_t mach);
205 void _mu_i_sv_instr_not (mu_sieve_machine_t mach);
206 void _mu_i_sv_instr_branch (mu_sieve_machine_t mach);
207 void _mu_i_sv_instr_brz (mu_sieve_machine_t mach);
208 void _mu_i_sv_instr_brnz (mu_sieve_machine_t mach);
209 void _mu_i_sv_instr_locus (mu_sieve_machine_t mach);
210 
211 int mu_i_sv_load_add_dir (mu_sieve_machine_t mach, const char *name);
212 
213 void mu_i_sv_register_standard_actions (mu_sieve_machine_t mach);
214 void mu_i_sv_register_standard_tests (mu_sieve_machine_t mach);
215 void mu_i_sv_register_standard_comparators (mu_sieve_machine_t mach);
216 
217 void mu_i_sv_error (mu_sieve_machine_t mach);
218 
219 void mu_i_sv_debug (mu_sieve_machine_t mach, size_t pc, const char *fmt, ...)
220   MU_PRINTFLIKE(3,4);
221 void mu_i_sv_debug_command (mu_sieve_machine_t mach, size_t pc,
222 			    char const *what);
223 void mu_i_sv_trace (mu_sieve_machine_t mach, const char *what);
224 
225 void mu_i_sv_valf (mu_sieve_machine_t mach, mu_stream_t str,
226 		   mu_sieve_value_t *val);
227 
228 typedef int (*mu_i_sv_interp_t) (char const *, size_t, char **, void *);
229 
230 int mu_i_sv_string_expand (char const *input,
231 			   mu_i_sv_interp_t interp, void *data, char **ret);
232 
233 int mu_i_sv_expand_encoded_char (char const *input, size_t len, char **exp, void *data);
234 
235 int mu_sieve_require_encoded_character (mu_sieve_machine_t mach,
236 					const char *name);
237 
238 void mu_i_sv_2nrealloc (mu_sieve_machine_t mach,
239 			void **pptr, size_t *pnmemb, size_t size);
240 
241 
242 mu_sieve_value_t *mu_i_sv_mach_arg (mu_sieve_machine_t mach, size_t n);
243 mu_sieve_value_t *mu_i_sv_mach_tagn (mu_sieve_machine_t mach, size_t n);
244 void mu_i_sv_lint_command (struct mu_sieve_machine *mach,
245 			   struct mu_sieve_node *node);
246 
247 
248 size_t  mu_i_sv_string_create (mu_sieve_machine_t mach, char *str);
249 
250 size_t mu_i_sv_id_num (mu_sieve_machine_t mach, char const *name);
251 char *mu_i_sv_id_str (mu_sieve_machine_t mach, size_t n);
252 void mu_i_sv_free_idspace (mu_sieve_machine_t mach);
253 
254 void mu_i_sv_copy_variables (mu_sieve_machine_t child,
255 			     mu_sieve_machine_t parent);
256 int mu_i_sv_expand_variables (char const *input, size_t len,
257 			      char **exp, void *data);
258 void mu_i_sv_init_variables (mu_sieve_machine_t mach);
259 
260 
261 
262