Imported Upstream version 2.7
[ossec-hids.git] / src / os_regex / os_regex_compile.c
1 /*   $OSSEC, os_regex_compile.c, v0.1, 2006/01/02, Daniel B. Cid$   */
2
3 /* Copyright (C) 2009 Trend Micro Inc.
4  * All right reserved.
5  *
6  * This program is a free software; you can redistribute it
7  * and/or modify it under the terms of the GNU General Public
8  * License (version 2) as published by the FSF - Free Software
9  * Foundation
10  */
11
12
13 #include <stdio.h>
14 #include <string.h>
15 #include <stdlib.h>
16 #include <ctype.h>
17
18 #include "os_regex.h"
19 #include "os_regex_internal.h"
20
21
22 /** int OSRegex_Compile(char *pattern, OSRegex *reg, int flags) v0.1
23  * Compile a regular expression to be used later.
24  * Allowed flags are:
25  *      - OS_CASE_SENSITIVE
26  *      - OS_RETURN_SUBSTRING
27  * Returns 1 on success or 0 on error.
28  * The error code is set on reg->error.
29  */
30 int OSRegex_Compile(char *pattern, OSRegex *reg, int flags)
31 {
32     int i = 0;
33     int count = 0;
34     int end_of_string = 0;
35     int parenthesis = 0;
36     int prts_size = 0;
37     int max_prts_size = 0;
38
39     char *pt;
40     char *new_str;
41     char *new_str_free = NULL;
42
43
44     /* Checking for references not initialized */
45     if(reg == NULL)
46     {
47         return(0);
48     }
49
50
51     /* Initializing OSRegex structure */
52     reg->error = 0;
53     reg->patterns = NULL;
54     reg->flags = NULL;
55     reg->prts_closure = NULL;
56     reg->prts_str = NULL;
57     reg->sub_strings = NULL;
58
59
60
61     /* The pattern can't be null */
62     if(pattern == NULL)
63     {
64         reg->error = OS_REGEX_PATTERN_NULL;
65         goto compile_error;
66     }
67
68     /* Maximum size of the pattern */
69     if(strlen(pattern) > OS_PATTERN_MAXSIZE)
70     {
71         reg->error = OS_REGEX_MAXSIZE;
72         goto compile_error;
73     }
74
75
76     /* Duping the pattern for our internal work */
77     new_str = strdup(pattern);
78     if(!new_str)
79     {
80         reg->error = OS_REGEX_OUTOFMEMORY;
81         goto compile_error;
82     }
83     new_str_free = new_str;
84     pt = new_str;
85
86
87     /* Getting the number of sub patterns */
88     do
89     {
90         if(*pt == BACKSLASH)
91         {
92             pt++;
93             if(!((*pt == 'w') ||
94                  (*pt == 'W') ||
95                  (*pt == 's') ||
96                  (*pt == 'S') ||
97                  (*pt == 'd') ||
98                  (*pt == 'D') ||
99                  (*pt == '.') ||
100                  (*pt == '(') ||
101                  (*pt == ')') ||
102                  (*pt == 'p') ||
103                  (*pt == 't') ||
104                  (*pt == '$') ||
105                  (*pt == '|') ||
106                  (*pt == '<') ||
107                  (*pt == '\\')))
108             {
109                 reg->error = OS_REGEX_BADREGEX;
110                 goto compile_error;
111             }
112
113             /* Giving the new values for each regex */
114             switch(*pt)
115             {
116                 case 'd': *pt = 1;break;
117                 case 'w': *pt = 2;break;
118                 case 's': *pt = 3;break;
119                 case 'p': *pt = 4;break;
120                 case '(': *pt = 5;break;
121                 case ')': *pt = 6;break;
122                 case '\\':*pt = 7;break;
123                 case 'D': *pt = 8;break;
124                 case 'W': *pt = 9;break;
125                 case 'S': *pt = 10;break;
126                 case '.': *pt = 11;break;
127                 case 't': *pt = 12;break;
128                 case '$': *pt = 13;break;
129                 case '|': *pt = 14;break;
130                 case '<': *pt = 15;break;
131             }
132             pt++;
133
134             continue;
135         }
136         else if(*pt == '(')
137         {
138             parenthesis++;
139         }
140         else if(*pt == ')')
141         {
142             /* Internally, open and closed are the same */
143             *pt = '(';
144             parenthesis--;
145             prts_size++;
146         }
147
148         /* We only allow one level of parenthesis */
149         if(parenthesis != 0 && parenthesis != 1)
150         {
151             reg->error = OS_REGEX_BADPARENTHESIS;
152             goto compile_error;
153         }
154
155         /* The pattern must be always lower case if
156          * case sensitive is set
157          */
158         if(!(flags & OS_CASE_SENSITIVE))
159         {
160             *pt = charmap[(uchar)*pt];
161         }
162
163         if(*pt == OR)
164         {
165             /* Each sub pattern must be closed on parenthesis */
166             if(parenthesis != 0)
167             {
168                 reg->error = OS_REGEX_BADPARENTHESIS;
169                 goto compile_error;
170             }
171             count++;
172         }
173         pt++;
174     }while(*pt != '\0');
175
176
177     /* After the whole pattern is read, the parenthesis must all be closed */
178     if(parenthesis != 0)
179     {
180         reg->error = OS_REGEX_BADPARENTHESIS;
181         goto compile_error;
182     }
183
184
185     /* Allocating the memory for the sub patterns */
186     count++;
187     reg->patterns = calloc(count +1, sizeof(char *));
188     reg->flags = calloc(count +1, sizeof(int));
189
190
191     /* For the substrings */
192     if((prts_size > 0) && (flags & OS_RETURN_SUBSTRING))
193     {
194         reg->prts_closure = calloc(count +1, sizeof(char **));
195         reg->prts_str = calloc(count +1, sizeof(char **));
196         if(!reg->prts_closure || !reg->prts_str)
197         {
198             reg->error = OS_REGEX_OUTOFMEMORY;
199             goto compile_error;
200         }
201     }
202
203
204     /* Memory allocation error check */
205     if(!reg->patterns || !reg->flags)
206     {
207         reg->error = OS_REGEX_OUTOFMEMORY;
208         goto compile_error;
209     }
210
211     /* Initializing each sub pattern */
212     for(i = 0; i<=count; i++)
213     {
214         reg->patterns[i] = NULL;
215         reg->flags[i] = 0;
216
217         /* The parenthesis closure if set */
218         if(reg->prts_closure)
219         {
220             reg->prts_closure[i] = NULL;
221             reg->prts_str[i] = NULL;
222         }
223     }
224     i = 0;
225
226
227     /* Reassigning pt to the beginning of the string */
228     pt = new_str;
229
230
231     /* Getting the sub patterns */
232     do
233     {
234         if((*pt == OR) || (*pt == '\0'))
235         {
236             if(*pt == '\0')
237             {
238                 end_of_string = 1;
239             }
240
241             *pt = '\0';
242
243             /* If string starts with ^, set the BEGIN SET flag */
244             if(*new_str == BEGINREGEX)
245             {
246                 new_str++;
247                 reg->flags[i]|=BEGIN_SET;
248             }
249
250             /* If string ends with $, set the END_SET flag */
251             if(*(pt-1) == ENDREGEX)
252             {
253                 *(pt-1) = '\0';
254                 reg->flags[i]|=END_SET;
255             }
256
257             reg->patterns[i] = strdup(new_str);
258
259             if(!reg->patterns[i])
260             {
261                 reg->error = OS_REGEX_OUTOFMEMORY;
262                 goto compile_error;
263
264             }
265
266
267             /* Setting the parenthesis closures */
268             /* The parenthesis closure if set */
269             if(reg->prts_closure)
270             {
271                 int tmp_int = 0;
272                 char *tmp_str;
273
274
275                 /* search the whole pattern for parenthesis */
276                 prts_size = 0;
277
278                 /* First loop we get the number of parenthesis.
279                  * We allocate the memory and loop again setting
280                  * the parenthesis closures.
281                  */
282                 tmp_str = reg->patterns[i];
283                 while(*tmp_str != '\0')
284                 {
285                     if(prts(*tmp_str))
286                     {
287                         prts_size++;
288                     }
289                     tmp_str++;
290                 }
291
292                 /* Getting the maximum number of parenthesis for
293                  * all sub strings. We need that to set up the maximum
294                  * number of substrings to be returned.
295                  */
296                 if(max_prts_size < prts_size)
297                 {
298                     max_prts_size = prts_size;
299                 }
300
301                 /* Allocating the memory */
302                 reg->prts_closure[i] = calloc(prts_size + 1, sizeof(char *));
303                 reg->prts_str[i] = calloc(prts_size + 1, sizeof(char *));
304                 if((reg->prts_closure[i] == NULL)||(reg->prts_str[i] == NULL))
305                 {
306                     reg->error = OS_REGEX_OUTOFMEMORY;
307                     goto compile_error;
308                 }
309
310                 /* Next loop to set the closures */
311                 tmp_str = reg->patterns[i];
312                 while(*tmp_str != '\0')
313                 {
314                     if(prts(*tmp_str))
315                     {
316                         if(tmp_int >= prts_size)
317                         {
318                             reg->error = OS_REGEX_BADPARENTHESIS;
319                             goto compile_error;
320                         }
321
322                         /* Setting to the pointer to the string */
323                         reg->prts_closure[i][tmp_int] = tmp_str;
324                         reg->prts_str[i][tmp_int] = NULL;
325
326                         tmp_int++;
327                     }
328
329                     tmp_str++;
330                 }
331             }
332
333
334             if(end_of_string)
335             {
336                 break;
337             }
338
339             new_str = ++pt;
340             i++;
341             continue;
342         }
343         pt++;
344
345     }while(!end_of_string);
346
347     /* Allocating sub string for the maximum number of parenthesis */
348     reg->sub_strings = calloc(max_prts_size + 1, sizeof(char *));
349     if(reg->sub_strings == NULL)
350     {
351         reg->error = OS_REGEX_OUTOFMEMORY;
352         goto compile_error;
353     }
354
355     /* Success return */
356     free(new_str_free);
357     return(1);
358
359
360     /* Error handling */
361     compile_error:
362
363     if(new_str_free)
364     {
365         free(new_str_free);
366     }
367
368     OSRegex_FreePattern(reg);
369
370     return(0);
371 }
372
373
374 /* EOF */