X-Git-Url: http://www.privoxy.org/gitweb/?p=privoxy.git;a=blobdiff_plain;f=pcrs.c;h=67b7b35635923f294e6d9e2570eed96882c0b8a9;hp=657a2867f68bb341569818a57889e069212a89c7;hb=36bed44da8971c4b75627ec86cc41163bfde81ae;hpb=fff4cf265d75e6d7d28e88a6fb1622fd904e095b diff --git a/pcrs.c b/pcrs.c index 657a2867..67b7b356 100644 --- a/pcrs.c +++ b/pcrs.c @@ -1,5 +1,3 @@ -const char pcrs_rcs[] = "$Id: pcrs.c,v 1.24 2007/01/05 15:46:12 fabiankeil Exp $"; - /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/pcrs.c,v $ @@ -17,159 +15,30 @@ const char pcrs_rcs[] = "$Id: pcrs.c,v 1.24 2007/01/05 15:46:12 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. + * This program is free software; you can redistribute it + * 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. * - * Revisions : - * $Log: pcrs.c,v $ - * Revision 1.24 2007/01/05 15:46:12 fabiankeil - * Don't use strlen() to calculate the length of - * the pcrs substitutes. They don't have to be valid C - * strings and getting their length wrong can result in - * user-controlled memory corruption. - * - * Thanks to Felix Gröbert for reporting the problem - * and providing the fix [#1627140]. - * - * Revision 1.23 2006/12/29 17:53:05 fabiankeil - * Fixed gcc43 conversion warnings. - * - * Revision 1.22 2006/12/24 17:34:20 fabiankeil - * Add pcrs_strerror() message for PCRE_ERROR_MATCHLIMIT - * and give a hint why an error code might be unknown. - * - * Catch NULL subjects early in pcrs_execute(). - * - * Revision 1.21 2006/07/18 14:48:47 david__schmidt - * Reorganizing the repository: swapping out what was HEAD (the old 3.1 branch) - * with what was really the latest development (the v_3_0_branch branch) - * - * Revision 1.19.2.4 2005/05/07 21:50:55 david__schmidt - * A few memory leaks plugged (mostly on error paths) - * - * Revision 1.19.2.3 2003/12/04 12:32:45 oes - * Append a trailing nullbyte to result to facilitate string processing - * - * Revision 1.19.2.2 2002/10/08 16:22:28 oes - * Bugfix: Need to check validity of backreferences explicitly, - * because when max_matches are reached and matches is expanded, - * realloc() does not zero the memory. Fixes Bug # 606227 - * - * Revision 1.19.2.1 2002/08/10 11:23:40 oes - * Include prce.h via project.h, where the appropriate - * source will have been selected - * - * Revision 1.19 2002/03/08 14:47:48 oes - * Cosmetics - * - * Revision 1.18 2002/03/08 14:17:14 oes - * Fixing -Wconversion warnings - * - * Revision 1.17 2002/03/08 13:45:48 oes - * Hiding internal functions - * - * Revision 1.16 2001/11/30 21:32:14 jongfoster - * Fixing signed/unsigned comparison (Andreas please check this!) - * One tab->space - * - * Revision 1.15 2001/09/20 16:11:06 steudten - * - * Add casting for some string functions. - * - * Revision 1.14 2001/09/09 21:41:57 oes - * Fixing yet another silly bug - * - * Revision 1.13 2001/09/06 14:05:59 oes - * Fixed silly bug - * - * Revision 1.12 2001/08/18 11:35:00 oes - * - Introduced pcrs_strerror() - * - made some NULL arguments non-fatal - * - added support for \n \r \e \b \t \f \a \0 in substitute - * - made quoting adhere to standard rules - * - added warning for bad backrefs - * - added pcrs_execute_list() - * - fixed comments - * - bugfix & cosmetics - * - * Revision 1.11 2001/08/15 15:32:03 oes - * - Added support for Perl's special variables $+, $' and $` - * - Improved the substitute parser - * - Replaced the hard limit for the maximum number of matches - * by dynamic reallocation - * - * Revision 1.10 2001/08/05 13:13:11 jongfoster - * Making parameters "const" where possible. - * - * Revision 1.9 2001/07/18 17:27:00 oes - * Changed interface; Cosmetics - * - * Revision 1.8 2001/06/29 21:45:41 oes - * Indentation, CRLF->LF, Tab-> Space - * - * Revision 1.7 2001/06/29 13:33:04 oes - * - Cleaned up, renamed and reordered functions, - * improved comments - * - Removed my_strsep - * - Replaced globalflag with a general flags int - * that holds PCRS_GLOBAL, PCRS_SUCCESS, and PCRS_TRIVIAL - * - Introduced trivial option that will prevent pcrs - * from honouring backreferences in the substitute, - * which is useful for large substitutes that are - * red in from somewhere and saves the pain of escaping - * the backrefs - * - Introduced convenience function pcrs_free_joblist() - * - Split pcrs_make_job() into pcrs_compile(), which still - * takes a complete s/// comand as argument and parses it, - * and a new function pcrs_make_job, which takes the - * three separate components. This should make for a - * much friendlier frontend. - * - Removed create_pcrs_job() which was useless - * - Fixed a bug in pcrs_execute - * - Success flag is now handled by pcrs instead of user - * - * Revision 1.6 2001/06/03 19:12:45 oes - * added FIXME - * - * Revision 1.5 2001/05/29 09:50:24 jongfoster - * (Fixed one int -> size_t) - * - * Revision 1.4 2001/05/25 14:12:40 oes - * Fixed bug: Empty substitutes now detected - * - * Revision 1.3 2001/05/25 11:03:55 oes - * Added sanity check for NULL jobs to pcrs_exec_substitution - * - * Revision 1.2 2001/05/22 18:46:04 oes - * - * Added support for PCRE_UNGREEDY behaviour to pcrs, - * which is selected by the (nonstandard and therefore - * capital) letter 'U' in the option string. - * It causes the quantifiers to be ungreedy by default. - * Appending a ? turns back to greedy (!). - * - * Revision 1.1.1.1 2001/05/15 13:59:02 oes - * Initial import of version 2.9.3 source tree - * - * *********************************************************************/ - + + +#include +#include +#include /* * Include project.h just so that the right pcre.h gets @@ -179,15 +48,11 @@ const char pcrs_rcs[] = "$Id: pcrs.c,v 1.24 2007/01/05 15:46:12 fabiankeil Exp $ /* For snprintf only */ #include "miscutil.h" - -#include -#include -#include +/* For xtoi */ +#include "encode.h" #include "pcrs.h" -const char pcrs_h_rcs[] = PCRS_H_VERSION; - /* * Internal prototypes */ @@ -195,13 +60,14 @@ const char pcrs_h_rcs[] = PCRS_H_VERSION; 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); +static int is_hex_sequence(const char *sequence); /********************************************************************* * * Function : pcrs_strerror * * Description : Return a string describing a given error code. - * + * * Parameters : * 1 : error = the error code * @@ -210,7 +76,9 @@ static pcrs_substitute *pcrs_compile_replacement(const char *replacement, int tr *********************************************************************/ const char *pcrs_strerror(const int error) { - if (error < 0) + static char buf[100]; + + if (error != 0) { switch (error) { @@ -224,7 +92,7 @@ const char *pcrs_strerror(const int error) case PCRE_ERROR_UNKNOWN_NODE: return "(pcre:) Bad node in pattern"; /* Can't happen / not passed: */ - case PCRE_ERROR_NOSUBSTRING: return "(pcre:) Fire in power supply"; + case PCRE_ERROR_NOSUBSTRING: return "(pcre:) Fire in power supply"; case PCRE_ERROR_NOMATCH: return "(pcre:) Water in power supply"; #ifdef PCRE_ERROR_MATCHLIMIT @@ -243,13 +111,17 @@ const char *pcrs_strerror(const int error) case PCRS_WARN_TRUNCATION: return "(pcrs:) At least one variable was too big and has been truncated before compilation"; - /* + /* * XXX: With the exception of PCRE_ERROR_MATCHLIMIT we * only catch PCRE errors that can happen with our internal * 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 */ @@ -269,12 +141,12 @@ const char *pcrs_strerror(const int error) * 'T' (trivial) options but pcrs needs them, the corresponding * flags are set if 'g'or 'T' is encountered. * Note: The 'T' and 'U' options do not conform to Perl. - * + * * Parameters : * 1 : optstring = string with options in perl syntax * 2 : flags = see description * - * Returns : option integer suitable for pcre + * Returns : option integer suitable for pcre * *********************************************************************/ static int pcrs_parse_perl_options(const char *optstring, int *flags) @@ -306,6 +178,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 @@ -333,10 +237,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; /* @@ -366,7 +273,7 @@ static pcrs_substitute *pcrs_compile_replacement(const char *replacement, int tr return NULL; } memset(text, '\0', length + 1); - + /* * In trivial mode, just copy the substitute text @@ -422,6 +329,20 @@ static pcrs_substitute *pcrs_compile_replacement(const char *replacement, int tr } i++; } + else if (is_hex_sequence(&replacement[i])) + { + /* + * Replace a hex sequence with a single + * character with the sequence's ascii value. + * e.g.: '\x7e' => '~' + */ + const int ascii_value = xtoi(&replacement[i+2]); + + assert(ascii_value >= 0); + assert(ascii_value < 256); + text[k++] = (char)ascii_value; + i += 4; + } else { quoted = 1; @@ -435,6 +356,13 @@ static pcrs_substitute *pcrs_compile_replacement(const char *replacement, int tr if (replacement[i] == '$' && !quoted && i < (int)(length - 1)) { char *symbol, symbols[] = "'`+&"; + if (l >= PCRS_MAX_SUBMATCHES) + { + freez(text); + freez(r); + *errptr = PCRS_WARN_BADREF; + return NULL; + } r->block_length[l] = (size_t)(k - r->block_offset[l]); /* Numerical backreferences */ @@ -446,14 +374,17 @@ static pcrs_substitute *pcrs_compile_replacement(const char *replacement, int tr } if (r->backref[l] > capturecount) { + freez(text); + freez(r); *errptr = PCRS_WARN_BADREF; + return NULL; } } /* Symbolic backreferences: */ else if (NULL != (symbol = strchr(symbols, replacement[i + 1]))) { - + if (symbol - symbols == 2) /* $+ */ { r->backref[l] = capturecount; @@ -464,7 +395,7 @@ static pcrs_substitute *pcrs_compile_replacement(const char *replacement, int tr } else /* $' or $` */ { - r->backref[l] = PCRS_MAX_SUBMATCHES + 1 - (symbol - symbols); + r->backref[l] = (int)(PCRS_MAX_SUBMATCHES + 1 - (symbol - symbols)); } i += 2; } @@ -475,19 +406,25 @@ 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 (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; } else { + freez(text); + freez(r); *errptr = PCRS_WARN_BADREF; - } + return NULL; + } continue; } - + plainchar: /* Plain chars are copied */ text[k++] = replacement[i++]; @@ -513,13 +450,13 @@ plainchar: * Function : pcrs_free_job * * Description : Frees the memory used by a pcrs_job struct and its - * dependant structures. + * dependent structures. * * Parameters : * 1 : job = pointer to the pcrs_job structure to be freed * * Returns : a pointer to the next job, if there was any, or - * NULL otherwise. + * NULL otherwise. * *********************************************************************/ pcrs_job *pcrs_free_job(pcrs_job *job) @@ -534,7 +471,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); @@ -563,7 +507,7 @@ pcrs_job *pcrs_free_job(pcrs_job *job) *********************************************************************/ void pcrs_free_joblist(pcrs_job *joblist) { - while ( NULL != (joblist = pcrs_free_job(joblist)) ) {}; + while (NULL != (joblist = pcrs_free_job(joblist))) {}; return; @@ -574,7 +518,7 @@ void pcrs_free_joblist(pcrs_job *joblist) * * Function : pcrs_compile_command * - * Description : Parses a string with a Perl-style s/// command, + * Description : Parses a string with a Perl-style s/// command, * calls pcrs_compile, and returns a corresponding * pcrs_job, or NULL if parsing or compiling the job * fails. @@ -594,11 +538,11 @@ pcrs_job *pcrs_compile_command(const char *command, int *errptr) int i, k, l, quoted = FALSE; size_t limit; char delimiter; - char *tokens[4]; + char *tokens[4]; pcrs_job *newjob; - - i = k = l = 0; - + + k = l = 0; + /* * Tokenize the perl command */ @@ -617,7 +561,7 @@ pcrs_job *pcrs_compile_command(const char *command, int *errptr) for (i = 0; i <= (int)limit; i++) { - + if (command[i] == delimiter && !quoted) { if (l == 3) @@ -629,7 +573,7 @@ pcrs_job *pcrs_compile_command(const char *command, int *errptr) tokens[++l] = tokens[0] + k; continue; } - + else if (command[i] == '\\' && !quoted) { quoted = TRUE; @@ -651,11 +595,11 @@ pcrs_job *pcrs_compile_command(const char *command, int *errptr) free(tokens[0]); return NULL; } - + newjob = pcrs_compile(tokens[1], tokens[2], tokens[3], errptr); free(tokens[0]); return newjob; - + } @@ -684,17 +628,18 @@ 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; - /* + /* * Handle NULL arguments */ if (pattern == NULL) pattern = ""; if (substitute == NULL) substitute = ""; - /* + /* * Get and init memory */ if (NULL == (newjob = (pcrs_job *)malloc(sizeof(pcrs_job)))) @@ -723,21 +668,25 @@ pcrs_job *pcrs_compile(const char *pattern, const char *substitute, const char * } +#ifdef PCRE_STUDY_JIT_COMPILE + 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; pcrs_free_job(newjob); return NULL; } - - /* - * Determine the number of capturing subpatterns. + + /* + * Determine the number of capturing subpatterns. * This is needed for handling $+ in the substitute. */ if (0 > (*errptr = pcre_fullinfo(newjob->pattern, newjob->hints, PCRE_INFO_CAPTURECOUNT, &capturecount))) @@ -745,7 +694,7 @@ pcrs_job *pcrs_compile(const char *pattern, const char *substitute, const char * pcrs_free_job(newjob); return NULL; } - + /* * Compile the substitute @@ -755,7 +704,7 @@ pcrs_job *pcrs_compile(const char *pattern, const char *substitute, const char * pcrs_free_job(newjob); return NULL; } - + return newjob; } @@ -770,7 +719,7 @@ pcrs_job *pcrs_compile(const char *pattern, const char *substitute, const char * * the joblist to the subject. * The subject itself is left untouched, memory for the result * is malloc()ed and it is the caller's responsibility to free - * the result when it's no longer needed. + * the result when it's no longer needed. * * Note: For convenient string handling, a null byte is * appended to the result. It does not count towards the @@ -780,8 +729,8 @@ pcrs_job *pcrs_compile(const char *pattern, const char *substitute, const char * * Parameters : * 1 : joblist = the chained list of pcrs_jobs to be executed * 2 : subject = the subject string - * 3 : subject_length = the subject's length - * 4 : result = char** for returning the result + * 3 : subject_length = the subject's length + * 4 : result = char** for returning the result * 5 : result_length = size_t* for returning the result's length * * Returns : On success, the number of substitutions that were made. @@ -795,10 +744,10 @@ int pcrs_execute_list(pcrs_job *joblist, char *subject, size_t subject_length, c pcrs_job *job; char *old, *new = NULL; int hits, total_hits; - + old = subject; *result_length = subject_length; - hits = total_hits = 0; + total_hits = 0; for (job = joblist; job != NULL; job = job->next) { @@ -840,8 +789,8 @@ int pcrs_execute_list(pcrs_job *joblist, char *subject, size_t subject_length, c * Parameters : * 1 : job = the pcrs_job to be executed * 2 : subject = the subject (== original) string - * 3 : subject_length = the subject's length - * 4 : result = char** for returning the result + * 3 : subject_length = the subject's length + * 4 : result = char** for returning the result (NULL on error) * 5 : result_length = size_t* for returning the result's length * * Returns : On success, the number of substitutions that were made. @@ -862,20 +811,19 @@ int pcrs_execute(pcrs_job *job, const char *subject, size_t subject_length, char pcrs_match *matches, *dummy; char *result_offset; - offset = i = k = 0; + offset = i = 0; + *result = NULL; - /* + /* * Sanity check & memory allocation */ if (job == NULL || job->pattern == NULL || job->substitute == NULL || NULL == subject) { - *result = NULL; return(PCRS_ERR_BADJOB); } if (NULL == (matches = (pcrs_match *)malloc((size_t)max_matches * sizeof(pcrs_match)))) { - *result = NULL; return(PCRS_ERR_NOMEM); } memset(matches, '\0', (size_t)max_matches * sizeof(pcrs_match)); @@ -897,13 +845,13 @@ int pcrs_execute(pcrs_job *job, const char *subject, size_t subject_length, char matches[i].submatch_offset[k] = offsets[2 * k]; /* Note: Non-found optional submatches have length -1-(-1)==0 */ - matches[i].submatch_length[k] = (size_t)(offsets[2 * k + 1] - offsets[2 * k]); + matches[i].submatch_length[k] = (size_t)(offsets[2 * k + 1] - offsets[2 * k]); /* reserve mem for each submatch as often as it is ref'd */ newsize += matches[i].submatch_length[k] * (size_t)job->substitute->backref_count[k]; } /* plus replacement text size minus match text size */ - newsize += job->substitute->length - matches[i].submatch_length[0]; + newsize += job->substitute->length - matches[i].submatch_length[0]; /* chunk before match */ matches[i].submatch_offset[PCRS_MAX_SUBMATCHES] = 0; @@ -922,7 +870,6 @@ int pcrs_execute(pcrs_job *job, const char *subject, size_t subject_length, char if (NULL == (dummy = (pcrs_match *)realloc(matches, (size_t)max_matches * sizeof(pcrs_match)))) { free(matches); - *result = NULL; return(PCRS_ERR_NOMEM); } matches = dummy; @@ -941,16 +888,16 @@ int pcrs_execute(pcrs_job *job, const char *subject, size_t subject_length, char else offset = offsets[1]; } - /* Pass pcre error through if (bad) failiure */ + /* Pass pcre error through if (bad) failure */ if (submatches < PCRE_ERROR_NOMATCH) { free(matches); - return submatches; + return submatches; } matches_found = i; - /* + /* * Get memory for the result (must be freed by caller!) * and append terminating null byte. */ @@ -965,7 +912,7 @@ int pcrs_execute(pcrs_job *job, const char *subject, size_t subject_length, char } - /* + /* * Replace */ offset = 0; @@ -974,7 +921,7 @@ int pcrs_execute(pcrs_job *job, const char *subject, size_t subject_length, char for (i = 0; i < matches_found; i++) { /* copy the chunk preceding the match */ - memcpy(result_offset, subject + offset, (size_t)(matches[i].submatch_offset[0] - offset)); + memcpy(result_offset, subject + offset, (size_t)(matches[i].submatch_offset[0] - offset)); result_offset += matches[i].submatch_offset[0] - offset; /* For every segment of the substitute.. */ @@ -1014,6 +961,33 @@ int pcrs_execute(pcrs_job *job, const char *subject, size_t subject_length, char } + +#define is_hex_digit(x) ((x) && strchr("0123456789ABCDEF", toupper(x))) + +/********************************************************************* + * + * Function : is_hex_sequence + * + * Description : Checks the first four characters of a string + * and decides if they are a valid hex sequence + * (like '\x40'). + * + * Parameters : + * 1 : sequence = The string to check + * + * Returns : Non-zero if it's valid sequence, or + * Zero if it isn't. + * + *********************************************************************/ +static int is_hex_sequence(const char *sequence) +{ + return (sequence[0] == '\\' && + sequence[1] == 'x' && + is_hex_digit(sequence[2]) && + is_hex_digit(sequence[3])); +} + + /* * Functions below this line are only part of the pcrs version * included in Privoxy. If you use any of them you should not @@ -1033,7 +1007,7 @@ int pcrs_execute(pcrs_job *job, const char *subject, size_t subject_length, char * 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); @@ -1077,7 +1051,7 @@ int pcrs_job_is_dynamic (char *job) * Parameters : * 1 : string = The string to search in * - * Returns : A safe delimiter if one was found, otherwise '\0'. + * Returns : A safe delimiter if one was found, otherwise '\0'. * *********************************************************************/ char pcrs_get_delimiter(const char *string) @@ -1086,8 +1060,8 @@ char pcrs_get_delimiter(const char *string) * Some characters that are unlikely to * be part of pcrs replacement strings. */ - char delimiters[] = "><§#+*~%^°-:;µ!@"; - char *d = delimiters; + static const char delimiters[] = "><#+*~%^-:;!@"; + const char *d = delimiters; /* Take the first delimiter that isn't part of the string */ while (*d && NULL != strchr(string, *d)) @@ -1099,7 +1073,6 @@ char pcrs_get_delimiter(const char *string) } - /********************************************************************* * * Function : pcrs_execute_single_command @@ -1111,11 +1084,11 @@ char pcrs_get_delimiter(const char *string) * * Parameters : * 1 : subject = the subject (== original) string - * 2 : pcrs_command = the pcrs command as string (s@foo@bar@) - * 3 : hits = int* for returning the number of modifications + * 2 : pcrs_command = the pcrs command as string (s@foo@bar@) + * 3 : hits = int* for returning the number of modifications * * Returns : NULL in case of errors, otherwise the - * result of the pcrs command. + * result of the pcrs command. * *********************************************************************/ char *pcrs_execute_single_command(const char *subject, const char *pcrs_command, int *hits) @@ -1145,7 +1118,6 @@ char *pcrs_execute_single_command(const char *subject, const char *pcrs_command, } -const static char warning[] = "... [too long, truncated]"; /********************************************************************* * * Function : pcrs_compile_dynamic_command @@ -1154,13 +1126,12 @@ const static char warning[] = "... [too long, truncated]"; * values of the variables and compiles it. * * Parameters : - * 1 : csp = Current client state (buffers, headers, etc...) - * 2 : pcrs_command = The dynamic pcrs command to compile - * 3 : v = NULL terminated array of variables and their values. - * 4 : error = pcrs error code + * 1 : pcrs_command = The dynamic pcrs command to compile + * 2 : v = NULL terminated array of variables and their values. + * 3 : error = pcrs error code * * Returns : NULL in case of hard errors, otherwise the - * compiled pcrs job. + * compiled pcrs job. * *********************************************************************/ pcrs_job *pcrs_compile_dynamic_command(char *pcrs_command, const struct pcrs_variable v[], int *error) @@ -1193,6 +1164,7 @@ pcrs_job *pcrs_compile_dynamic_command(char *pcrs_command, const struct pcrs_var { /* No proper delimiter found */ *error = PCRS_ERR_CMDSYNTAX; + freez(pcrs_command_tmp); return NULL; } @@ -1212,6 +1184,7 @@ pcrs_job *pcrs_compile_dynamic_command(char *pcrs_command, const struct pcrs_var * with a truncation message and close the pattern * properly. */ + static const char warning[] = "... [too long, truncated]"; const size_t trailer_size = sizeof(warning) + 3; /* 3 for d + "gT" */ char *trailer_start = buf + sizeof(buf) - trailer_size;