remove 'illegal' (non-reentrant) log logic from signal handler
[oweals/gnunet.git] / src / regex / regex_test_random.c
1 /*
2      This file is part of GNUnet
3      Copyright (C) 2012 GNUnet e.V.
4
5      GNUnet is free software: you can redistribute it and/or modify it
6      under the terms of the GNU Affero General Public License as published
7      by the Free Software Foundation, either version 3 of the License,
8      or (at your option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      Affero General Public License for more details.
14
15      You should have received a copy of the GNU Affero General Public License
16      along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18      SPDX-License-Identifier: AGPL3.0-or-later
19  */
20 /**
21  * @file src/regex/regex_test_random.c
22  * @brief functions for creating random regular expressions and strings
23  * @author Maximilian Szengel
24  */
25 #include "platform.h"
26 #include "regex_test_lib.h"
27 #include "gnunet_crypto_lib.h"
28 #include "regex_internal.h"
29
30
31 /**
32  * Get a (pseudo) random valid literal for building a regular expression.
33  *
34  * @return random valid literal
35  */
36 static char
37 get_random_literal ()
38 {
39   uint32_t ridx;
40
41   ridx =
42     GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
43                               (uint32_t) strlen (ALLOWED_LITERALS));
44
45   return ALLOWED_LITERALS[ridx];
46 }
47
48
49 /**
50  * Generate a (pseudo) random regular expression of length 'rx_length', as well
51  * as a (optional) string that will be matched by the generated regex. The
52  * returned regex needs to be freed.
53  *
54  * @param rx_length length of the random regex.
55  * @param matching_str (optional) pointer to a string that will contain a string
56  *                     that will be matched by the generated regex, if
57  *                     'matching_str' pointer was not NULL. Make sure you
58  *                     allocated at least rx_length+1 bytes for this sting.
59  *
60  * @return NULL if 'rx_length' is 0, a random regex of length 'rx_length', which
61  *         needs to be freed, otherwise.
62  */
63 char *
64 REGEX_TEST_generate_random_regex (size_t rx_length, char *matching_str)
65 {
66   char *rx;
67   char *rx_p;
68   char *matching_strp;
69   unsigned int i;
70   unsigned int char_op_switch;
71   unsigned int last_was_op;
72   int rx_op;
73   char current_char;
74
75   if (0 == rx_length)
76     return NULL;
77
78   if (NULL != matching_str)
79     matching_strp = matching_str;
80   else
81     matching_strp = NULL;
82
83   rx = GNUNET_malloc (rx_length + 1);
84   rx_p = rx;
85   current_char = 0;
86   last_was_op = 1;
87
88   for (i = 0; i < rx_length; i++)
89   {
90     char_op_switch = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 2);
91
92     if ((0 == char_op_switch) && ! last_was_op)
93     {
94       last_was_op = 1;
95       rx_op = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 4);
96
97       switch (rx_op)
98       {
99       case 0:
100         current_char = '+';
101         break;
102
103       case 1:
104         current_char = '*';
105         break;
106
107       case 2:
108         current_char = '?';
109         break;
110
111       case 3:
112         if (i < rx_length - 1)       /* '|' cannot be at the end */
113           current_char = '|';
114         else
115           current_char = get_random_literal ();
116         break;
117       }
118     }
119     else
120     {
121       current_char = get_random_literal ();
122       last_was_op = 0;
123     }
124
125     if ((NULL != matching_strp) &&
126         ((current_char != '+') && (current_char != '*') && (current_char !=
127                                                             '?') &&
128          (current_char != '|') ))
129     {
130       *matching_strp = current_char;
131       matching_strp++;
132     }
133
134     *rx_p = current_char;
135     rx_p++;
136   }
137   *rx_p = '\0';
138   if (NULL != matching_strp)
139     *matching_strp = '\0';
140
141   return rx;
142 }
143
144
145 /**
146  * Generate a random string of maximum length 'max_len' that only contains literals allowed
147  * in a regular expression. The string might be 0 chars long but is garantueed
148  * to be shorter or equal to 'max_len'.
149  *
150  * @param max_len maximum length of the string that should be generated.
151  *
152  * @return random string that needs to be freed.
153  */
154 char *
155 REGEX_TEST_generate_random_string (size_t max_len)
156 {
157   unsigned int i;
158   char *str;
159   size_t len;
160
161   if (1 > max_len)
162     return GNUNET_strdup ("");
163
164   len = (size_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, max_len);
165   str = GNUNET_malloc (len + 1);
166
167   for (i = 0; i < len; i++)
168   {
169     str[i] = get_random_literal ();
170   }
171
172   str[i] = '\0';
173
174   return str;
175 }