X-Git-Url: http://www.privoxy.org/gitweb/?p=privoxy.git;a=blobdiff_plain;f=pcrs.c;h=83100983b6475d0b7d75cbae6280db8595227d28;hp=4d112271a08a71f63d622f0ad72c8d684fccf21d;hb=31265b1b2d8f5b81cbde0fcada6271d800430c59;hpb=37b60a3260c885bfa3f33d94a186a2741fca52f5 diff --git a/pcrs.c b/pcrs.c index 4d112271..83100983 100644 --- a/pcrs.c +++ b/pcrs.c @@ -1,4 +1,3 @@ -const char pcrs_rcs[] = "$Id: pcrs.c,v 1.46 2014/11/14 10:40:10 fabiankeil Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/pcrs.c,v $ @@ -17,21 +16,20 @@ const char pcrs_rcs[] = "$Id: pcrs.c,v 1.46 2014/11/14 10:40:10 fabiankeil Exp $ * Copyright (C) 2006, 2007 Fabian Keil * * This program is free software; you can redistribute it - * and/or modify it under the terms of the GNU Lesser - * General Public License (LGPL), version 2.1, which should - * be included in this distribution (see LICENSE.txt), with - * the exception that the permission to replace that license - * with the GNU General Public License (GPL) given in section - * 3 is restricted to version 2 of the GPL. + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at + * your option) any later version. * * This program is distributed in the hope that it will * be useful, but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A - * PARTICULAR PURPOSE. See the license for more details. + * PARTICULAR PURPOSE. See the GNU General Public + * License for more details. * - * The GNU Lesser General Public License should be included - * with this file. If not, you can view it at - * http://www.gnu.org/licenses/lgpl.html + * The GNU General Public License should be included with + * this file. If not, you can view it at + * http://www.gnu.org/copyleft/gpl.html * or write to the Free Software Foundation, Inc., 59 * Temple Place - Suite 330, Boston, MA 02111-1307, USA. * @@ -55,8 +53,6 @@ const char pcrs_rcs[] = "$Id: pcrs.c,v 1.46 2014/11/14 10:40:10 fabiankeil Exp $ #include "pcrs.h" -const char pcrs_h_rcs[] = PCRS_H_VERSION; - /* * Internal prototypes */ @@ -80,6 +76,8 @@ static int is_hex_sequence(const char *sequence); *********************************************************************/ const char *pcrs_strerror(const int error) { + static char buf[100]; + if (error != 0) { switch (error) @@ -119,7 +117,11 @@ const char *pcrs_strerror(const int error) * version. If Privoxy is linked against a newer * PCRE version all bets are off ... */ - default: return "Unknown error. Privoxy out of sync with PCRE?"; + default: + snprintf(buf, sizeof(buf), + "Error code %d. For details, check the pcre documentation.", + error); + return buf; } } /* error >= 0: No error */ @@ -166,6 +168,7 @@ static int pcrs_parse_perl_options(const char *optstring, int *flags) case 'o': break; case 's': rc |= PCRE_DOTALL; break; case 'x': rc |= PCRE_EXTENDED; break; + case 'D': *flags |= PCRS_DYNAMIC; break; case 'U': rc |= PCRE_UNGREEDY; break; case 'T': *flags |= PCRS_TRIVIAL; break; default: break; @@ -176,6 +179,38 @@ static int pcrs_parse_perl_options(const char *optstring, int *flags) } +#ifdef FUZZ +/********************************************************************* + * + * Function : pcrs_compile_fuzzed_replacement + * + * Description : Wrapper around pcrs_compile_replacement() for + * fuzzing purposes. + * + * Parameters : + * 1 : replacement = replacement part of s/// operator + * in perl syntax + * 2 : errptr = pointer to an integer in which error + * conditions can be returned. + * + * Returns : pcrs_substitute data structure, or NULL if an + * error is encountered. In that case, *errptr has + * the reason. + * + *********************************************************************/ +extern pcrs_substitute *pcrs_compile_fuzzed_replacement(const char *replacement, int *errptr) +{ + int capturecount = PCRS_MAX_SUBMATCHES; /* XXX: fuzzworthy? */ + int trivial_flag = 0; /* We don't want to fuzz strncpy() */ + + *errptr = 0; /* XXX: Should pcrs_compile_replacement() do this? */ + + return pcrs_compile_replacement(replacement, trivial_flag, capturecount, errptr); + +} +#endif + + /********************************************************************* * * Function : pcrs_compile_replacement @@ -203,10 +238,13 @@ static int pcrs_parse_perl_options(const char *optstring, int *flags) static pcrs_substitute *pcrs_compile_replacement(const char *replacement, int trivialflag, int capturecount, int *errptr) { int i, k, l, quoted; - size_t length; char *text; pcrs_substitute *r; - +#ifndef FUZZ + size_t length; +#else + static size_t length; +#endif i = k = l = quoted = 0; /* @@ -243,7 +281,7 @@ static pcrs_substitute *pcrs_compile_replacement(const char *replacement, int tr */ if (trivialflag) { - text = strncpy(text, replacement, length + 1); + strlcpy(text, replacement, length + 1); k = (int)length; } @@ -369,8 +407,11 @@ static pcrs_substitute *pcrs_compile_replacement(const char *replacement, int tr goto plainchar; } + assert(r->backref[l] < PCRS_MAX_SUBMATCHES + 2); /* Valid and in range? -> record */ - if (0 <= r->backref[l] && r->backref[l] < PCRS_MAX_SUBMATCHES + 2) + if ((0 <= r->backref[l]) && + (r->backref[l] < PCRS_MAX_SUBMATCHES + 2) && + (l < PCRS_MAX_SUBMATCHES - 1)) { r->backref_count[r->backref[l]] += 1; r->block_offset[++l] = k; @@ -431,7 +472,14 @@ pcrs_job *pcrs_free_job(pcrs_job *job) { next = job->next; if (job->pattern != NULL) free(job->pattern); - if (job->hints != NULL) free(job->hints); + if (job->hints != NULL) + { +#ifdef PCRE_CONFIG_JIT + pcre_free_study(job->hints); +#else + free(job->hints); +#endif + } if (job->substitute != NULL) { if (job->substitute->text != NULL) free(job->substitute->text); @@ -581,6 +629,7 @@ pcrs_job *pcrs_compile(const char *pattern, const char *substitute, const char * int flags; int capturecount; const char *error; + int pcre_study_options = 0; *errptr = 0; @@ -620,11 +669,18 @@ pcrs_job *pcrs_compile(const char *pattern, const char *substitute, const char * } +#ifdef PCRE_STUDY_JIT_COMPILE + if (!(flags & PCRS_DYNAMIC)) + { + pcre_study_options = PCRE_STUDY_JIT_COMPILE; + } +#endif + /* * Generate hints. This has little overhead, since the * hints will be NULL for a boring pattern anyway. */ - newjob->hints = pcre_study(newjob->pattern, 0, &error); + newjob->hints = pcre_study(newjob->pattern, pcre_study_options, &error); if (error != NULL) { *errptr = PCRS_ERR_STUDY; @@ -955,7 +1011,7 @@ static int is_hex_sequence(const char *sequence) * FALSE * *********************************************************************/ -int pcrs_job_is_dynamic (char *job) +int pcrs_job_is_dynamic(char *job) { const char delimiter = job[1]; const size_t length = strlen(job); @@ -1066,7 +1122,6 @@ char *pcrs_execute_single_command(const char *subject, const char *pcrs_command, } -static const char warning[] = "... [too long, truncated]"; /********************************************************************* * * Function : pcrs_compile_dynamic_command @@ -1123,7 +1178,7 @@ pcrs_job *pcrs_compile_dynamic_command(char *pcrs_command, const struct pcrs_var */ assert(NULL == strchr(v->name, d)); - ret = snprintf(buf, sizeof(buf), "s%c\\$%s%c%s%cgT", d, v->name, d, v->value, d); + ret = snprintf(buf, sizeof(buf), "s%c\\$%s%c%s%cDgT", d, v->name, d, v->value, d); assert(ret >= 0); if (ret >= sizeof(buf)) { @@ -1133,10 +1188,11 @@ pcrs_job *pcrs_compile_dynamic_command(char *pcrs_command, const struct pcrs_var * with a truncation message and close the pattern * properly. */ - const size_t trailer_size = sizeof(warning) + 3; /* 3 for d + "gT" */ + static const char warning[] = "... [too long, truncated]"; + const size_t trailer_size = sizeof(warning) + 4; /* 4 for d + "DgT" */ char *trailer_start = buf + sizeof(buf) - trailer_size; - ret = snprintf(trailer_start, trailer_size, "%s%cgT", warning, d); + ret = snprintf(trailer_start, trailer_size, "%s%cDgT", warning, d); assert(ret == trailer_size - 1); assert(sizeof(buf) == strlen(buf) + 1); truncation = 1;