rugged 1.9.4 → 1.9.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/lib/rugged/version.rb +1 -1
  3. data/vendor/libgit2/CMakeLists.txt +1 -1
  4. data/vendor/libgit2/COPYING +83 -11
  5. data/vendor/libgit2/cmake/SelectRegex.cmake +8 -3
  6. data/vendor/libgit2/deps/pcre2/CMakeLists.txt +110 -0
  7. data/vendor/libgit2/deps/pcre2/LICENCE.md +104 -0
  8. data/vendor/libgit2/deps/pcre2/config.h.in +54 -0
  9. data/vendor/libgit2/deps/pcre2/pcre2.h +1079 -0
  10. data/vendor/libgit2/deps/pcre2/pcre2_auto_possess.c +1416 -0
  11. data/vendor/libgit2/deps/{pcre/pcre_chartables.c → pcre2/pcre2_chartables.c} +41 -47
  12. data/vendor/libgit2/deps/{pcre/pcre_ord2utf8.c → pcre2/pcre2_chkdint.c} +36 -36
  13. data/vendor/libgit2/deps/pcre2/pcre2_compile.c +11345 -0
  14. data/vendor/libgit2/deps/pcre2/pcre2_compile.h +356 -0
  15. data/vendor/libgit2/deps/pcre2/pcre2_compile_cgroup.c +632 -0
  16. data/vendor/libgit2/deps/pcre2/pcre2_compile_class.c +2777 -0
  17. data/vendor/libgit2/deps/pcre2/pcre2_config.c +250 -0
  18. data/vendor/libgit2/deps/pcre2/pcre2_context.c +557 -0
  19. data/vendor/libgit2/deps/pcre2/pcre2_convert.c +1263 -0
  20. data/vendor/libgit2/deps/{pcre/pcre_dfa_exec.c → pcre2/pcre2_dfa_match.c} +1402 -943
  21. data/vendor/libgit2/deps/pcre2/pcre2_error.c +384 -0
  22. data/vendor/libgit2/deps/pcre2/pcre2_extuni.c +159 -0
  23. data/vendor/libgit2/deps/pcre2/pcre2_find_bracket.c +217 -0
  24. data/vendor/libgit2/deps/pcre2/pcre2_fuzzsupport.c +844 -0
  25. data/vendor/libgit2/deps/pcre2/pcre2_internal.h +2353 -0
  26. data/vendor/libgit2/deps/pcre2/pcre2_intmodedep.h +1044 -0
  27. data/vendor/libgit2/deps/pcre2/pcre2_maketables.c +177 -0
  28. data/vendor/libgit2/deps/pcre2/pcre2_match.c +8244 -0
  29. data/vendor/libgit2/deps/pcre2/pcre2_match_data.c +184 -0
  30. data/vendor/libgit2/deps/pcre2/pcre2_match_next.c +171 -0
  31. data/vendor/libgit2/deps/{pcre/pcre_newline.c → pcre2/pcre2_newline.c} +92 -63
  32. data/vendor/libgit2/deps/{pcre/pcre_refcount.c → pcre2/pcre2_ord2utf.c} +64 -38
  33. data/vendor/libgit2/deps/pcre2/pcre2_pattern_info.c +430 -0
  34. data/vendor/libgit2/deps/pcre2/pcre2_printint_inc.h +1098 -0
  35. data/vendor/libgit2/deps/pcre2/pcre2_script_run.c +344 -0
  36. data/vendor/libgit2/deps/pcre2/pcre2_serialize.c +284 -0
  37. data/vendor/libgit2/deps/pcre2/pcre2_string_utils.c +199 -0
  38. data/vendor/libgit2/deps/pcre2/pcre2_study.c +2087 -0
  39. data/vendor/libgit2/deps/pcre2/pcre2_substitute.c +1761 -0
  40. data/vendor/libgit2/deps/pcre2/pcre2_substring.c +553 -0
  41. data/vendor/libgit2/deps/pcre2/pcre2_tables.c +310 -0
  42. data/vendor/libgit2/deps/pcre2/pcre2_ucd.c +5805 -0
  43. data/vendor/libgit2/deps/pcre2/pcre2_ucp.h +408 -0
  44. data/vendor/libgit2/deps/pcre2/pcre2_ucptables_inc.h +1596 -0
  45. data/vendor/libgit2/deps/pcre2/pcre2_util.h +179 -0
  46. data/vendor/libgit2/deps/pcre2/pcre2_valid_utf.c +397 -0
  47. data/vendor/libgit2/deps/pcre2/pcre2_xclass.c +547 -0
  48. data/vendor/libgit2/include/git2/common.h +13 -1
  49. data/vendor/libgit2/include/git2/version.h +2 -2
  50. data/vendor/libgit2/src/libgit2/blame.c +6 -0
  51. data/vendor/libgit2/src/libgit2/delta.c +8 -0
  52. data/vendor/libgit2/src/libgit2/indexer.c +3 -2
  53. data/vendor/libgit2/src/libgit2/settings.c +9 -0
  54. data/vendor/libgit2/src/libgit2/streams/openssl.c +4 -1
  55. data/vendor/libgit2/src/libgit2/submodule.c +77 -12
  56. data/vendor/libgit2/src/libgit2/transports/http.c +4 -4
  57. data/vendor/libgit2/src/libgit2/transports/smart_pkt.c +2 -1
  58. data/vendor/libgit2/src/util/fs_path.h +10 -10
  59. data/vendor/libgit2/src/util/regexp.c +27 -12
  60. data/vendor/libgit2/src/util/regexp.h +7 -2
  61. metadata +44 -37
  62. data/vendor/libgit2/deps/pcre/CMakeLists.txt +0 -140
  63. data/vendor/libgit2/deps/pcre/COPYING +0 -5
  64. data/vendor/libgit2/deps/pcre/LICENCE +0 -93
  65. data/vendor/libgit2/deps/pcre/cmake/COPYING-CMAKE-SCRIPTS +0 -22
  66. data/vendor/libgit2/deps/pcre/cmake/FindEditline.cmake +0 -17
  67. data/vendor/libgit2/deps/pcre/cmake/FindPackageHandleStandardArgs.cmake +0 -58
  68. data/vendor/libgit2/deps/pcre/cmake/FindReadline.cmake +0 -29
  69. data/vendor/libgit2/deps/pcre/config.h.in +0 -57
  70. data/vendor/libgit2/deps/pcre/pcre.h +0 -641
  71. data/vendor/libgit2/deps/pcre/pcre_byte_order.c +0 -319
  72. data/vendor/libgit2/deps/pcre/pcre_compile.c +0 -9815
  73. data/vendor/libgit2/deps/pcre/pcre_config.c +0 -190
  74. data/vendor/libgit2/deps/pcre/pcre_exec.c +0 -7173
  75. data/vendor/libgit2/deps/pcre/pcre_fullinfo.c +0 -245
  76. data/vendor/libgit2/deps/pcre/pcre_get.c +0 -669
  77. data/vendor/libgit2/deps/pcre/pcre_globals.c +0 -86
  78. data/vendor/libgit2/deps/pcre/pcre_internal.h +0 -2787
  79. data/vendor/libgit2/deps/pcre/pcre_jit_compile.c +0 -11913
  80. data/vendor/libgit2/deps/pcre/pcre_maketables.c +0 -156
  81. data/vendor/libgit2/deps/pcre/pcre_printint.c +0 -834
  82. data/vendor/libgit2/deps/pcre/pcre_string_utils.c +0 -211
  83. data/vendor/libgit2/deps/pcre/pcre_study.c +0 -1686
  84. data/vendor/libgit2/deps/pcre/pcre_tables.c +0 -727
  85. data/vendor/libgit2/deps/pcre/pcre_ucd.c +0 -3644
  86. data/vendor/libgit2/deps/pcre/pcre_valid_utf8.c +0 -301
  87. data/vendor/libgit2/deps/pcre/pcre_version.c +0 -98
  88. data/vendor/libgit2/deps/pcre/pcre_xclass.c +0 -268
  89. data/vendor/libgit2/deps/pcre/pcreposix.c +0 -420
  90. data/vendor/libgit2/deps/pcre/pcreposix.h +0 -117
  91. data/vendor/libgit2/deps/pcre/ucp.h +0 -224
@@ -0,0 +1,844 @@
1
+ /*************************************************
2
+ * Perl-Compatible Regular Expressions *
3
+ *************************************************/
4
+
5
+ /* PCRE is a library of functions to support regular expressions whose syntax
6
+ and semantics are as close as possible to those of the Perl 5 language.
7
+
8
+ Written by Philip Hazel
9
+ Original API code Copyright (c) 1997-2012 University of Cambridge
10
+ New API code Copyright (c) 2016-2023 University of Cambridge
11
+
12
+ -----------------------------------------------------------------------------
13
+ Redistribution and use in source and binary forms, with or without
14
+ modification, are permitted provided that the following conditions are met:
15
+
16
+ * Redistributions of source code must retain the above copyright notice,
17
+ this list of conditions and the following disclaimer.
18
+
19
+ * Redistributions in binary form must reproduce the above copyright
20
+ notice, this list of conditions and the following disclaimer in the
21
+ documentation and/or other materials provided with the distribution.
22
+
23
+ * Neither the name of the University of Cambridge nor the names of its
24
+ contributors may be used to endorse or promote products derived from
25
+ this software without specific prior written permission.
26
+
27
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
28
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
31
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37
+ POSSIBILITY OF SUCH DAMAGE.
38
+ -----------------------------------------------------------------------------
39
+ */
40
+
41
+
42
+ /***************************************************************************
43
+ Fuzzer driver for PCRE2. Given an arbitrary string of bytes and a length, it
44
+ tries to compile and match it, deriving options from the string itself. If
45
+ STANDALONE is defined, a main program that calls the driver with the contents
46
+ of specified files is compiled, and commentary on what is happening is output.
47
+ If an argument starts with '=' the rest of it it is taken as a literal string
48
+ rather than a file name. This allows easy testing of short strings.
49
+
50
+ Written by Philip Hazel, October 2016
51
+ Updated February 2024 (Addison Crump added 16-bit/32-bit and JIT support)
52
+ Further updates March/April/May 2024 by PH
53
+ ***************************************************************************/
54
+
55
+
56
+ #include <errno.h>
57
+ #include <stdarg.h>
58
+ #include <stdio.h>
59
+ #include <stdlib.h>
60
+ #include <string.h>
61
+ #include <unistd.h>
62
+
63
+ /* stack size adjustment */
64
+ #include <sys/time.h>
65
+ #include <sys/resource.h>
66
+
67
+ #define STACK_SIZE_MB 256
68
+ #define JIT_SIZE_LIMIT (200 * 1024)
69
+
70
+ #ifndef PCRE2_CODE_UNIT_WIDTH
71
+ #define PCRE2_CODE_UNIT_WIDTH 8
72
+ #endif
73
+
74
+ #include "pcre2_internal.h"
75
+
76
+ #define MAX_MATCH_SIZE 1000
77
+
78
+ #define DFA_WORKSPACE_COUNT 100
79
+
80
+ /* When adding new compile or match options, remember to update the functions
81
+ below that output them. */
82
+
83
+ #define ALLOWED_COMPILE_OPTIONS \
84
+ (PCRE2_ANCHORED|PCRE2_ALLOW_EMPTY_CLASS|PCRE2_ALT_BSUX|PCRE2_ALT_CIRCUMFLEX| \
85
+ PCRE2_ALT_EXTENDED_CLASS|PCRE2_ALT_VERBNAMES|PCRE2_AUTO_CALLOUT| \
86
+ PCRE2_CASELESS|PCRE2_DOLLAR_ENDONLY| \
87
+ PCRE2_DOTALL|PCRE2_DUPNAMES|PCRE2_ENDANCHORED|PCRE2_EXTENDED| \
88
+ PCRE2_EXTENDED_MORE|PCRE2_FIRSTLINE| \
89
+ PCRE2_MATCH_UNSET_BACKREF|PCRE2_MULTILINE|PCRE2_NEVER_BACKSLASH_C| \
90
+ PCRE2_NO_AUTO_CAPTURE| \
91
+ PCRE2_NO_AUTO_POSSESS|PCRE2_NO_DOTSTAR_ANCHOR|PCRE2_NO_START_OPTIMIZE| \
92
+ PCRE2_UCP|PCRE2_UNGREEDY|PCRE2_USE_OFFSET_LIMIT| \
93
+ PCRE2_UTF)
94
+
95
+ #define ALLOWED_MATCH_OPTIONS \
96
+ (PCRE2_ANCHORED|PCRE2_ENDANCHORED|PCRE2_NOTBOL|PCRE2_NOTEOL|PCRE2_NOTEMPTY| \
97
+ PCRE2_NOTEMPTY_ATSTART|PCRE2_PARTIAL_HARD| \
98
+ PCRE2_PARTIAL_SOFT)
99
+
100
+ #define BASE_MATCH_OPTIONS \
101
+ (PCRE2_NO_JIT|PCRE2_DISABLE_RECURSELOOP_CHECK)
102
+
103
+
104
+ #if defined(SUPPORT_DIFF_FUZZ) || defined(STANDALONE)
105
+ static void print_compile_options(FILE *stream, uint32_t compile_options)
106
+ {
107
+ fprintf(stream, "Compile options %s%.8x =",
108
+ (compile_options == PCRE2_NEVER_BACKSLASH_C)? "(base) " : "",
109
+ compile_options);
110
+
111
+ fprintf(stream, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
112
+ ((compile_options & PCRE2_ALT_BSUX) != 0)? " alt_bsux" : "",
113
+ ((compile_options & PCRE2_ALT_CIRCUMFLEX) != 0)? " alt_circumflex" : "",
114
+ ((compile_options & PCRE2_ALT_EXTENDED_CLASS) != 0)? "alt_extended_class" : "",
115
+ ((compile_options & PCRE2_ALT_VERBNAMES) != 0)? " alt_verbnames" : "",
116
+ ((compile_options & PCRE2_ALLOW_EMPTY_CLASS) != 0)? " allow_empty_class" : "",
117
+ ((compile_options & PCRE2_ANCHORED) != 0)? " anchored" : "",
118
+ ((compile_options & PCRE2_AUTO_CALLOUT) != 0)? " auto_callout" : "",
119
+ ((compile_options & PCRE2_CASELESS) != 0)? " caseless" : "",
120
+ ((compile_options & PCRE2_DOLLAR_ENDONLY) != 0)? " dollar_endonly" : "",
121
+ ((compile_options & PCRE2_DOTALL) != 0)? " dotall" : "",
122
+ ((compile_options & PCRE2_DUPNAMES) != 0)? " dupnames" : "",
123
+ ((compile_options & PCRE2_ENDANCHORED) != 0)? " endanchored" : "",
124
+ ((compile_options & PCRE2_EXTENDED) != 0)? " extended" : "",
125
+ ((compile_options & PCRE2_EXTENDED_MORE) != 0)? " extended_more" : "",
126
+ ((compile_options & PCRE2_FIRSTLINE) != 0)? " firstline" : "",
127
+ ((compile_options & PCRE2_MATCH_UNSET_BACKREF) != 0)? " match_unset_backref" : "",
128
+ ((compile_options & PCRE2_MULTILINE) != 0)? " multiline" : "",
129
+ ((compile_options & PCRE2_NEVER_BACKSLASH_C) != 0)? " never_backslash_c" : "",
130
+ ((compile_options & PCRE2_NEVER_UCP) != 0)? " never_ucp" : "",
131
+ ((compile_options & PCRE2_NEVER_UTF) != 0)? " never_utf" : "",
132
+ ((compile_options & PCRE2_NO_AUTO_CAPTURE) != 0)? " no_auto_capture" : "",
133
+ ((compile_options & PCRE2_NO_AUTO_POSSESS) != 0)? " no_auto_possess" : "",
134
+ ((compile_options & PCRE2_NO_DOTSTAR_ANCHOR) != 0)? " no_dotstar_anchor" : "",
135
+ ((compile_options & PCRE2_NO_UTF_CHECK) != 0)? " no_utf_check" : "",
136
+ ((compile_options & PCRE2_NO_START_OPTIMIZE) != 0)? " no_start_optimize" : "",
137
+ ((compile_options & PCRE2_UCP) != 0)? " ucp" : "",
138
+ ((compile_options & PCRE2_UNGREEDY) != 0)? " ungreedy" : "",
139
+ ((compile_options & PCRE2_USE_OFFSET_LIMIT) != 0)? " use_offset_limit" : "",
140
+ ((compile_options & PCRE2_UTF) != 0)? " utf" : "");
141
+ }
142
+
143
+ static void print_match_options(FILE *stream, uint32_t match_options)
144
+ {
145
+ fprintf(stream, "Match options %s%.8x =",
146
+ (match_options == BASE_MATCH_OPTIONS)? "(base) " : "", match_options);
147
+
148
+ fprintf(stream, "%s%s%s%s%s%s%s%s%s%s%s\n",
149
+ ((match_options & PCRE2_ANCHORED) != 0)? " anchored" : "",
150
+ ((match_options & PCRE2_DISABLE_RECURSELOOP_CHECK) != 0)? " disable_recurseloop_check" : "",
151
+ ((match_options & PCRE2_ENDANCHORED) != 0)? " endanchored" : "",
152
+ ((match_options & PCRE2_NO_JIT) != 0)? " no_jit" : "",
153
+ ((match_options & PCRE2_NO_UTF_CHECK) != 0)? " no_utf_check" : "",
154
+ ((match_options & PCRE2_NOTBOL) != 0)? " notbol" : "",
155
+ ((match_options & PCRE2_NOTEMPTY) != 0)? " notempty" : "",
156
+ ((match_options & PCRE2_NOTEMPTY_ATSTART) != 0)? " notempty_atstart" : "",
157
+ ((match_options & PCRE2_NOTEOL) != 0)? " noteol" : "",
158
+ ((match_options & PCRE2_PARTIAL_HARD) != 0)? " partial_hard" : "",
159
+ ((match_options & PCRE2_PARTIAL_SOFT) != 0)? " partial_soft" : "");
160
+ }
161
+
162
+
163
+ /* This function can print an error message at all code unit widths. */
164
+
165
+ static void print_error(FILE *f, int errorcode, const char *text, ...)
166
+ {
167
+ PCRE2_UCHAR buffer[256];
168
+ PCRE2_UCHAR *p = buffer;
169
+ va_list ap;
170
+ va_start(ap, text);
171
+ vfprintf(f, text, ap);
172
+ va_end(ap);
173
+ pcre2_get_error_message(errorcode, buffer, 256);
174
+ while (*p != 0) fprintf(f, "%c", *p++);
175
+ printf("\n");
176
+ }
177
+ #endif /* defined(SUPPORT_DIFF_FUZZ || defined(STANDALONE) */
178
+
179
+
180
+ #ifdef SUPPORT_JIT
181
+ #ifdef SUPPORT_DIFF_FUZZ
182
+ static void dump_matches(FILE *stream, int count, pcre2_match_data *match_data)
183
+ {
184
+ int errorcode;
185
+
186
+ for (int index = 0; index < count; index++)
187
+ {
188
+ PCRE2_UCHAR *bufferptr = NULL;
189
+ PCRE2_SIZE bufflen = 0;
190
+
191
+ errorcode = pcre2_substring_get_bynumber(match_data, index, &bufferptr,
192
+ &bufflen);
193
+
194
+ if (errorcode >= 0)
195
+ {
196
+ fprintf(stream, "Match %d (hex encoded): ", index);
197
+ for (PCRE2_SIZE i = 0; i < bufflen; i++)
198
+ {
199
+ fprintf(stream, "%02x", bufferptr[i]);
200
+ }
201
+ fprintf(stream, "\n");
202
+ }
203
+ else
204
+ {
205
+ print_error(stream, errorcode, "Match %d failed: ", index);
206
+ }
207
+ }
208
+ }
209
+
210
+ /* This function describes the current test case being evaluated, then aborts */
211
+
212
+ static void describe_failure(
213
+ const char *task,
214
+ const PCRE2_UCHAR *data,
215
+ PCRE2_SIZE size,
216
+ uint32_t compile_options,
217
+ uint32_t match_options,
218
+ int errorcode,
219
+ int errorcode_jit,
220
+ int matches,
221
+ int matches_jit,
222
+ pcre2_match_data *match_data,
223
+ pcre2_match_data *match_data_jit
224
+ ) {
225
+
226
+ fprintf(stderr, "Encountered failure while performing %s; context:\n", task);
227
+
228
+ fprintf(stderr, "Pattern/sample string (hex encoded): ");
229
+ for (size_t i = 0; i < size; i++)
230
+ {
231
+ fprintf(stderr, "%02x", data[i]);
232
+ }
233
+ fprintf(stderr, "\n");
234
+
235
+ print_compile_options(stderr, compile_options);
236
+ print_match_options(stderr, match_options);
237
+
238
+ if (errorcode < 0)
239
+ {
240
+ print_error(stderr, errorcode, "Non-JIT'd operation emitted an error: ");
241
+ }
242
+
243
+ if (matches >= 0)
244
+ {
245
+ fprintf(stderr, "Non-JIT'd operation did not emit an error.\n");
246
+ if (match_data != NULL)
247
+ {
248
+ fprintf(stderr, "%d matches discovered by non-JIT'd regex:\n", matches);
249
+ dump_matches(stderr, matches, match_data);
250
+ fprintf(stderr, "\n");
251
+ }
252
+ }
253
+
254
+ if (errorcode_jit < 0)
255
+ {
256
+ print_error(stderr, errorcode_jit, "JIT'd operation emitted error %d:",
257
+ errorcode_jit);
258
+ }
259
+
260
+ if (matches_jit >= 0)
261
+ {
262
+ fprintf(stderr, "JIT'd operation did not emit an error.\n");
263
+ if (match_data_jit != NULL)
264
+ {
265
+ fprintf(stderr, "%d matches discovered by JIT'd regex:\n", matches_jit);
266
+ dump_matches(stderr, matches_jit, match_data_jit);
267
+ fprintf(stderr, "\n");
268
+ }
269
+ }
270
+
271
+ abort();
272
+ }
273
+ #endif /* SUPPORT_DIFF_FUZZ */
274
+ #endif /* SUPPORT_JIT */
275
+
276
+ /* This is the callout function. Its only purpose is to halt matching if there
277
+ are more than 100 callouts, as one way of stopping too much time being spent on
278
+ fruitless matches. The callout data is a pointer to the counter. */
279
+
280
+ static int callout_function(pcre2_callout_block *cb, void *callout_data)
281
+ {
282
+ (void)cb; /* Avoid unused parameter warning */
283
+ *((uint32_t *)callout_data) += 1;
284
+ return (*((uint32_t *)callout_data) > 100)? PCRE2_ERROR_CALLOUT : 0;
285
+ }
286
+
287
+ /* Putting in this apparently unnecessary prototype prevents gcc from giving a
288
+ "no previous prototype" warning when compiling at high warning level. */
289
+
290
+ int LLVMFuzzerInitialize(int *, char ***);
291
+
292
+ int LLVMFuzzerTestOneInput(unsigned char *, size_t);
293
+
294
+ int LLVMFuzzerInitialize(int *argc, char ***argv)
295
+ {
296
+ int rc;
297
+ struct rlimit rlim;
298
+ getrlimit(RLIMIT_STACK, &rlim);
299
+ rlim.rlim_cur = STACK_SIZE_MB * 1024 * 1024;
300
+ if (rlim.rlim_cur > rlim.rlim_max)
301
+ {
302
+ fprintf(stderr, "Hard stack size limit is too small\n");
303
+ _exit(1);
304
+ }
305
+ rc = setrlimit(RLIMIT_STACK, &rlim);
306
+ if (rc != 0)
307
+ {
308
+ fprintf(stderr, "Failed to expand stack size\n");
309
+ _exit(1);
310
+ }
311
+
312
+ (void)argc; /* Avoid "unused parameter" warnings */
313
+ (void)argv;
314
+ return 0;
315
+ }
316
+
317
+ /* Here's the driving function. */
318
+
319
+ int LLVMFuzzerTestOneInput(unsigned char *data, size_t size)
320
+ {
321
+ PCRE2_UCHAR *wdata;
322
+ PCRE2_UCHAR *newwdata = NULL;
323
+ uint32_t compile_options;
324
+ uint32_t match_options;
325
+ uint64_t random_options;
326
+ pcre2_match_data *match_data = NULL;
327
+ #ifdef SUPPORT_JIT
328
+ pcre2_match_data *match_data_jit = NULL;
329
+ #endif
330
+ pcre2_compile_context *compile_context = NULL;
331
+ pcre2_match_context *match_context = NULL;
332
+ size_t match_size;
333
+ int dfa_workspace[DFA_WORKSPACE_COUNT];
334
+
335
+ if (size < sizeof(random_options)) return -1;
336
+
337
+ random_options = *(uint64_t *)(data);
338
+ data += sizeof(random_options);
339
+ wdata = (PCRE2_UCHAR *)data;
340
+ size -= sizeof(random_options);
341
+ size /= PCRE2_CODE_UNIT_WIDTH / 8;
342
+
343
+ /* PCRE2 compiles quantified groups by replicating them. In certain cases of
344
+ very large quantifiers this can lead to unacceptably long JIT compile times. To
345
+ get around this, we scan the data string for large quantifiers that follow a
346
+ closing parenthesis, and reduce the value of the quantifier to 10, assuming
347
+ that this will make minimal difference to the detection of bugs.
348
+
349
+ Do the same for quantifiers that follow a closing square bracket, because
350
+ classes that contain a number of non-ascii characters can take a lot of time
351
+ when matching.
352
+
353
+ We have to make a copy of the input because oss-fuzz complains if we overwrite
354
+ the original. Start the scan at the second character so there can be a
355
+ lookbehind for a backslash, and end it before the end so that the next
356
+ character can be checked for an opening brace. */
357
+
358
+ if (size > 3)
359
+ {
360
+ newwdata = malloc(size * sizeof(PCRE2_UCHAR));
361
+ memcpy(newwdata, wdata, size * sizeof(PCRE2_UCHAR));
362
+ wdata = newwdata;
363
+
364
+ for (size_t i = 1; i < size - 2; i++)
365
+ {
366
+ size_t j;
367
+
368
+ if ((wdata[i] != ')' && wdata[i] != ']') || wdata[i-1] == '\\' ||
369
+ wdata[i+1] != '{')
370
+ continue;
371
+ i++; /* Points to '{' */
372
+
373
+ /* Loop for two values in a quantifier. Offset i points to brace or comma
374
+ at the start of the loop. */
375
+
376
+ for (int ii = 0; ii < 2; ii++)
377
+ {
378
+ int q = 0;
379
+
380
+ if (i >= size - 1) goto END_QSCAN; /* Can happen for , */
381
+
382
+ /* Ignore leading spaces. */
383
+
384
+ while (wdata[i+1] == ' ' || wdata[i+1] == '\t')
385
+ {
386
+ i++;
387
+ if (i >= size - 1) goto END_QSCAN;
388
+ }
389
+
390
+ /* Ignore non-significant leading zeros. */
391
+
392
+ while (wdata[i+1] == '0' && i+2 < size && wdata[i+2] >= '0' &&
393
+ wdata[i+2] <= '9')
394
+ {
395
+ i++;
396
+ if (i >= size - 1) goto END_QSCAN;
397
+ }
398
+
399
+ /* Scan for a number ending in brace, or comma in the first iteration,
400
+ optionally preceded by space. */
401
+
402
+ for (j = i + 1; j < size && j < i + 7; j++)
403
+ {
404
+ if (wdata[j] == ' ' || wdata[j] == '\t')
405
+ {
406
+ j++;
407
+ while (j < size && (wdata[j] == ' ' || wdata[j] == '\t')) j++;
408
+ if (j >= size) goto OUTERLOOP;
409
+ if (wdata[j] != '}' && wdata[j] != ',') goto OUTERLOOP;
410
+ }
411
+ if (wdata[j] == '}' || (ii == 0 && wdata[j] == ',')) break;
412
+
413
+ if (wdata[j] < '0' || wdata[j] > '9')
414
+ {
415
+ j--; /* Ensure this character is checked next. The */
416
+ goto OUTERLOOP; /* string might be (e.g.) "){9){234}" */
417
+ }
418
+ q = q * 10 + (wdata[j] - '0');
419
+ }
420
+
421
+ if (j >= size) goto END_QSCAN; /* End of data */
422
+
423
+ /* Hit ',' or '}' or read 6 digits. Six digits is a number > 65536 which
424
+ is the maximum quantifier. Leave such numbers alone. */
425
+
426
+ if (j >= i + 7 || q > 65535) goto OUTERLOOP;
427
+
428
+ /* Limit the quantifier size to 10 */
429
+
430
+ if (q > 10)
431
+ {
432
+ #ifdef STANDALONE
433
+ printf("Reduced quantifier value %d to 10.\n", q);
434
+ #endif
435
+ for (size_t k = i + 1; k < j; k++) wdata[k] = '0';
436
+ wdata[j - 2] = '1';
437
+ }
438
+
439
+ /* Advance to end of number and break if reached closing brace (continue
440
+ after comma, which is only valid in the first time round this loop). */
441
+
442
+ i = j;
443
+ if (wdata[i] == '}') break;
444
+ }
445
+
446
+ /* Continue along the data string */
447
+
448
+ OUTERLOOP:
449
+ i = j;
450
+ continue;
451
+ }
452
+ }
453
+ END_QSCAN:
454
+
455
+ /* Limiting the length of the subject for matching stops fruitless searches
456
+ in large trees taking too much time. */
457
+
458
+ match_size = (size > MAX_MATCH_SIZE)? MAX_MATCH_SIZE : size;
459
+
460
+ /* Create a compile context, and set a limit on the size of the compiled
461
+ pattern. This stops the fuzzer using vast amounts of memory. */
462
+
463
+ compile_context = pcre2_compile_context_create(NULL);
464
+ if (compile_context == NULL)
465
+ {
466
+ #ifdef STANDALONE
467
+ fprintf(stderr, "** Failed to create compile context block\n");
468
+ #endif
469
+ abort();
470
+ }
471
+ pcre2_set_max_pattern_compiled_length(compile_context, 10*1024*1024);
472
+
473
+ /* Ensure that all undefined option bits are zero (waste of time trying them)
474
+ and also that PCRE2_NO_UTF_CHECK is unset, as there is no guarantee that the
475
+ input is valid UTF. Also unset PCRE2_NEVER_UTF and PCRE2_NEVER_UCP as there is
476
+ no reason to disallow UTF and UCP. Force PCRE2_NEVER_BACKSLASH_C to be set
477
+ because \C in random patterns is highly likely to cause a crash. */
478
+
479
+ compile_options = ((random_options >> 32) & ALLOWED_COMPILE_OPTIONS) |
480
+ PCRE2_NEVER_BACKSLASH_C;
481
+ match_options = (((uint32_t)random_options) & ALLOWED_MATCH_OPTIONS) |
482
+ BASE_MATCH_OPTIONS;
483
+
484
+ /* Discard partial matching if PCRE2_ENDANCHORED is set, because they are not
485
+ allowed together and just give an immediate error return. */
486
+
487
+ if (((compile_options|match_options) & PCRE2_ENDANCHORED) != 0)
488
+ match_options &= ~(PCRE2_PARTIAL_HARD|PCRE2_PARTIAL_SOFT);
489
+
490
+ /* Do the compile with and without the options, and after a successful compile,
491
+ likewise do the match with and without the options. */
492
+
493
+ for (int i = 0; i < 2; i++)
494
+ {
495
+ uint32_t callout_count;
496
+ int errorcode;
497
+ #ifdef SUPPORT_JIT
498
+ int errorcode_jit;
499
+ #ifdef SUPPORT_DIFF_FUZZ
500
+ int matches = 0;
501
+ int matches_jit = 0;
502
+ #endif
503
+ #endif
504
+ PCRE2_SIZE erroroffset;
505
+ pcre2_code *code;
506
+
507
+ #ifdef STANDALONE
508
+ printf("\n");
509
+ print_compile_options(stdout, compile_options);
510
+ #endif
511
+
512
+ code = pcre2_compile((PCRE2_SPTR)wdata, (PCRE2_SIZE)size, compile_options,
513
+ &errorcode, &erroroffset, compile_context);
514
+
515
+ /* Compilation succeeded */
516
+
517
+ if (code != NULL)
518
+ {
519
+ int j;
520
+ uint32_t save_match_options = match_options;
521
+
522
+ /* Call JIT compile only if the compiled pattern is not too big. */
523
+
524
+ #ifdef SUPPORT_JIT
525
+ int jit_ret = -1;
526
+ if (((struct pcre2_real_code *)code)->blocksize <= JIT_SIZE_LIMIT)
527
+ {
528
+ #ifdef STANDALONE
529
+ printf("Compile succeeded; calling JIT compile\n");
530
+ #endif
531
+ jit_ret = pcre2_jit_compile(code, PCRE2_JIT_COMPLETE);
532
+ #ifdef STANDALONE
533
+ if (jit_ret < 0) printf("JIT compile error %d\n", jit_ret);
534
+ #endif
535
+ }
536
+ else
537
+ {
538
+ #ifdef STANDALONE
539
+ printf("Not calling JIT: compiled pattern is too long "
540
+ "(%ld bytes; limit=%d)\n",
541
+ ((struct pcre2_real_code *)code)->blocksize, JIT_SIZE_LIMIT);
542
+ #endif
543
+ }
544
+ #endif /* SUPPORT_JIT */
545
+
546
+ /* Create match data and context blocks only when we first need them. Set
547
+ low match and depth limits to avoid wasting too much searching large
548
+ pattern trees. Almost all matches are going to fail. */
549
+
550
+ if (match_data == NULL)
551
+ {
552
+ match_data = pcre2_match_data_create(32, NULL);
553
+ #ifdef SUPPORT_JIT
554
+ match_data_jit = pcre2_match_data_create(32, NULL);
555
+ if (match_data == NULL || match_data_jit == NULL)
556
+ #else
557
+ if (match_data == NULL)
558
+ #endif
559
+ {
560
+ #ifdef STANDALONE
561
+ fprintf(stderr, "** Failed to create match data block\n");
562
+ #endif
563
+ abort();
564
+ }
565
+ }
566
+
567
+ if (match_context == NULL)
568
+ {
569
+ match_context = pcre2_match_context_create(NULL);
570
+ if (match_context == NULL)
571
+ {
572
+ #ifdef STANDALONE
573
+ fprintf(stderr, "** Failed to create match context block\n");
574
+ #endif
575
+ abort();
576
+ }
577
+ (void)pcre2_set_match_limit(match_context, 100);
578
+ (void)pcre2_set_depth_limit(match_context, 100);
579
+ (void)pcre2_set_callout(match_context, callout_function, &callout_count);
580
+ }
581
+
582
+ /* Match twice, with and without options. */
583
+
584
+ #ifdef STANDALONE
585
+ printf("\n");
586
+ #endif
587
+ for (j = 0; j < 2; j++)
588
+ {
589
+ #ifdef STANDALONE
590
+ print_match_options(stdout, match_options);
591
+ #endif
592
+
593
+ callout_count = 0;
594
+ errorcode = pcre2_match(code, (PCRE2_SPTR)wdata, (PCRE2_SIZE)match_size, 0,
595
+ match_options, match_data, match_context);
596
+
597
+ #ifdef STANDALONE
598
+ if (errorcode >= 0) printf("Match returned %d\n", errorcode); else
599
+ print_error(stdout, errorcode, "Match failed: error %d: ", errorcode);
600
+ #endif
601
+
602
+ /* If JIT is enabled, do a JIT match and, if appropriately compiled, compare
603
+ with the interpreter. */
604
+
605
+ #ifdef SUPPORT_JIT
606
+ if (jit_ret >= 0)
607
+ {
608
+ #ifdef STANDALONE
609
+ printf("Matching with JIT\n");
610
+ #endif
611
+ callout_count = 0;
612
+ errorcode_jit = pcre2_match(code, (PCRE2_SPTR)wdata, (PCRE2_SIZE)match_size, 0,
613
+ match_options & ~PCRE2_NO_JIT, match_data_jit, match_context);
614
+
615
+ #ifdef STANDALONE
616
+ if (errorcode_jit >= 0)
617
+ printf("Match returned %d\n", errorcode_jit);
618
+ else
619
+ print_error(stdout, errorcode_jit, "JIT match failed: error %d: ",
620
+ errorcode_jit);
621
+ #else
622
+ (void)errorcode_jit; /* Avoid compiler warning */
623
+ #endif /* STANDALONE */
624
+
625
+ /* With differential matching enabled, compare with interpreter. */
626
+
627
+ #ifdef SUPPORT_DIFF_FUZZ
628
+ matches = errorcode;
629
+ matches_jit = errorcode_jit;
630
+
631
+ if (errorcode_jit != errorcode)
632
+ {
633
+ if (!(errorcode < 0 && errorcode_jit < 0) &&
634
+ errorcode != PCRE2_ERROR_MATCHLIMIT && errorcode != PCRE2_ERROR_CALLOUT &&
635
+ errorcode_jit != PCRE2_ERROR_MATCHLIMIT && errorcode_jit != PCRE2_ERROR_JIT_STACKLIMIT && errorcode_jit != PCRE2_ERROR_CALLOUT)
636
+ {
637
+ describe_failure("match errorcode comparison", wdata, size, compile_options, match_options, errorcode, errorcode_jit, matches, matches_jit, match_data, match_data_jit);
638
+ }
639
+ }
640
+ else
641
+ {
642
+ for (int index = 0; index < errorcode; index++)
643
+ {
644
+ PCRE2_UCHAR *bufferptr, *bufferptr_jit;
645
+ PCRE2_SIZE bufflen, bufflen_jit;
646
+
647
+ bufferptr = bufferptr_jit = NULL;
648
+ bufflen = bufflen_jit = 0;
649
+
650
+ errorcode = pcre2_substring_get_bynumber(match_data, (uint32_t) index, &bufferptr, &bufflen);
651
+ errorcode_jit = pcre2_substring_get_bynumber(match_data_jit, (uint32_t) index, &bufferptr_jit, &bufflen_jit);
652
+
653
+ if (errorcode != errorcode_jit)
654
+ {
655
+ describe_failure("match entry errorcode comparison", wdata, size,
656
+ compile_options, match_options, errorcode, errorcode_jit,
657
+ matches, matches_jit, match_data, match_data_jit);
658
+ }
659
+
660
+ if (errorcode >= 0)
661
+ {
662
+ if (bufflen != bufflen_jit)
663
+ {
664
+ describe_failure("match entry length comparison", wdata, size,
665
+ compile_options, match_options, errorcode, errorcode_jit,
666
+ matches, matches_jit, match_data, match_data_jit);
667
+ }
668
+
669
+ if (memcmp(bufferptr, bufferptr_jit, bufflen) != 0)
670
+ {
671
+ describe_failure("match entry content comparison", wdata, size,
672
+ compile_options, match_options, errorcode, errorcode_jit,
673
+ matches, matches_jit, match_data, match_data_jit);
674
+ }
675
+ }
676
+
677
+ pcre2_substring_free(bufferptr);
678
+ pcre2_substring_free(bufferptr_jit);
679
+ }
680
+ }
681
+ #endif /* SUPPORT_DIFF_FUZZ */
682
+ }
683
+ #endif /* SUPPORT_JIT */
684
+
685
+ if (match_options == BASE_MATCH_OPTIONS) break; /* Don't do same twice */
686
+ match_options = BASE_MATCH_OPTIONS; /* For second time */
687
+ }
688
+
689
+ /* Match with DFA twice, with and without options, but remove options that
690
+ are not allowed with DFA. */
691
+
692
+ match_options = save_match_options & ~BASE_MATCH_OPTIONS;
693
+
694
+ #ifdef STANDALONE
695
+ printf("\n");
696
+ #endif
697
+
698
+ for (j = 0; j < 2; j++)
699
+ {
700
+ #ifdef STANDALONE
701
+ printf("DFA match options %.8x =", match_options);
702
+ printf("%s%s%s%s%s%s%s%s%s\n",
703
+ ((match_options & PCRE2_ANCHORED) != 0)? " anchored" : "",
704
+ ((match_options & PCRE2_ENDANCHORED) != 0)? " endanchored" : "",
705
+ ((match_options & PCRE2_NO_UTF_CHECK) != 0)? " no_utf_check" : "",
706
+ ((match_options & PCRE2_NOTBOL) != 0)? " notbol" : "",
707
+ ((match_options & PCRE2_NOTEMPTY) != 0)? " notempty" : "",
708
+ ((match_options & PCRE2_NOTEMPTY_ATSTART) != 0)? " notempty_atstart" : "",
709
+ ((match_options & PCRE2_NOTEOL) != 0)? " noteol" : "",
710
+ ((match_options & PCRE2_PARTIAL_HARD) != 0)? " partial_hard" : "",
711
+ ((match_options & PCRE2_PARTIAL_SOFT) != 0)? " partial_soft" : "");
712
+ #endif
713
+
714
+ callout_count = 0;
715
+ errorcode = pcre2_dfa_match(code, (PCRE2_SPTR)wdata,
716
+ (PCRE2_SIZE)match_size, 0, match_options, match_data,
717
+ match_context, dfa_workspace, DFA_WORKSPACE_COUNT);
718
+
719
+ #ifdef STANDALONE
720
+ if (errorcode >= 0)
721
+ printf("Match returned %d\n", errorcode);
722
+ else
723
+ print_error(stdout, errorcode, "DFA match failed: error %d: ", errorcode);
724
+ #endif
725
+
726
+ if (match_options == 0) break; /* No point doing same twice */
727
+ match_options = 0; /* For second time */
728
+ }
729
+
730
+ match_options = save_match_options; /* Reset for the second compile */
731
+ pcre2_code_free(code);
732
+ }
733
+
734
+ /* Compilation failed */
735
+
736
+ else
737
+ {
738
+ #ifdef STANDALONE
739
+ print_error(stdout, errorcode, "Error %d at offset %lu: ", errorcode,
740
+ erroroffset);
741
+ #else
742
+ if (errorcode == PCRE2_ERROR_INTERNAL) abort();
743
+ #endif
744
+ }
745
+
746
+ if (compile_options == PCRE2_NEVER_BACKSLASH_C) break; /* Avoid same twice */
747
+ compile_options = PCRE2_NEVER_BACKSLASH_C; /* For second time */
748
+ }
749
+
750
+ /* Tidy up before exiting */
751
+
752
+ if (match_data != NULL) pcre2_match_data_free(match_data);
753
+ #ifdef SUPPORT_JIT
754
+ if (match_data_jit != NULL) pcre2_match_data_free(match_data_jit);
755
+ #endif
756
+ free(newwdata);
757
+ if (match_context != NULL) pcre2_match_context_free(match_context);
758
+ if (compile_context != NULL) pcre2_compile_context_free(compile_context);
759
+ return 0;
760
+ }
761
+
762
+
763
+ /* Optional main program. */
764
+
765
+ #ifdef STANDALONE
766
+ int main(int argc, char **argv)
767
+ {
768
+ LLVMFuzzerInitialize(&argc, &argv);
769
+
770
+ if (argc < 2)
771
+ {
772
+ printf("** No arguments given\n");
773
+ return 0;
774
+ }
775
+
776
+ for (int i = 1; i < argc; i++)
777
+ {
778
+ size_t filelen;
779
+ size_t readsize;
780
+ unsigned char *buffer;
781
+ FILE *f;
782
+
783
+ /* Handle a literal string. Copy to an exact size buffer so that checks for
784
+ overrunning work. */
785
+
786
+ if (argv[i][0] == '=')
787
+ {
788
+ readsize = strlen(argv[i]) - 1;
789
+ printf("------ <Literal> ------\n");
790
+ printf("Length = %lu\n", readsize);
791
+ printf("%.*s\n", (int)readsize, argv[i]+1);
792
+ buffer = (unsigned char *)malloc(readsize);
793
+ if (buffer == NULL)
794
+ printf("** Failed to allocate %lu bytes of memory\n", readsize);
795
+ else
796
+ {
797
+ memcpy(buffer, argv[i]+1, readsize);
798
+ LLVMFuzzerTestOneInput(buffer, readsize);
799
+ free(buffer);
800
+ }
801
+ continue;
802
+ }
803
+
804
+ /* Handle a string given in a file */
805
+
806
+ f = fopen(argv[i], "rb");
807
+ if (f == NULL)
808
+ {
809
+ printf("** Failed to open %s: %s\n", argv[i], strerror(errno));
810
+ continue;
811
+ }
812
+
813
+ printf("------ %s ------\n", argv[i]);
814
+
815
+ fseek(f, 0, SEEK_END);
816
+ filelen = ftell(f);
817
+ fseek(f, 0, SEEK_SET);
818
+
819
+ buffer = (unsigned char *)malloc(filelen);
820
+ if (buffer == NULL)
821
+ {
822
+ printf("** Failed to allocate %lu bytes of memory\n", filelen);
823
+ fclose(f);
824
+ continue;
825
+ }
826
+
827
+ readsize = fread(buffer, 1, filelen, f);
828
+ fclose(f);
829
+
830
+ if (readsize != filelen)
831
+ printf("** File size is %lu but fread() returned %lu\n", filelen, readsize);
832
+ else
833
+ {
834
+ printf("Length = %lu\n", filelen);
835
+ LLVMFuzzerTestOneInput(buffer, filelen);
836
+ }
837
+ free(buffer);
838
+ }
839
+
840
+ return 0;
841
+ }
842
+ #endif /* STANDALONE */
843
+
844
+ /* End */