... which exposes Privoxy internals to input from files or stdout.
Mainly tested with American Fuzzy Lop. For details see:
https://www.fabiankeil.de/talks/fuzzing-on-freebsd/
This work was partially funded with donations and done
as part of the Privoxy month in 2015.
Hohoho.
# Note: GNUmakefile is built automatically from GNUmakefile.in
#
-# $Id: GNUmakefile.in,v 1.251 2016/05/08 12:46:15 fabiankeil Exp $
+# $Id: GNUmakefile.in,v 1.252 2016/07/28 08:16:04 fabiankeil Exp $
#
# Written by and Copyright (C) 2001-2016 members of the
# Privoxy team. https://www.privoxy.org/
CLIENT_TAG_SRC = @FEATURE_CLIENT_TAGS_ONLY@client-tags.c
CLIENT_TAG_OBJS = @FEATURE_CLIENT_TAGS_ONLY@client-tags.@OBJEXT@
+FUZZ_SRC = @FUZZ_ONLY@fuzz.c
+FUZZ_OBJS = @FUZZ_ONLY@fuzz.@OBJEXT@
+
W32_SRC = @WIN_ONLY@w32log.c w32taskbar.c win32.c w32svrapi.c
W32_FILES = @WIN_ONLY@w32.res
W32_OBJS = @WIN_ONLY@$(W32_SRC:.c=.@OBJEXT@) $(W32_FILES)
# PThreads library, if needed.
PTHREAD_LIB = @PTHREAD_ONLY@@PTHREAD_LIB@
-SRCS = $(C_SRC) $(CLIENT_TAG_SRC) $(W32_SRC) $(PCRS_SRC) $(PCRE_SRC) $(REGEX_SRC)
-OBJS = $(C_OBJS) $(CLIENT_TAG_OBJS) $(W32_OBJS) $(PCRS_OBJS) $(PCRE_OBJS) $(REGEX_OBJS)
+SRCS = $(C_SRC) $(CLIENT_TAG_SRC) $(FUZZ_SRC) $(W32_SRC) $(PCRS_SRC) $(PCRE_SRC) $(REGEX_SRC)
+OBJS = $(C_OBJS) $(CLIENT_TAG_OBJS) $(FUZZ_OBJS) $(W32_OBJS) $(PCRS_OBJS) $(PCRE_OBJS) $(REGEX_OBJS)
HDRS = $(C_HDRS) $(W32_HDRS) $(PCRS_HDRS) $(PCRE_OBJS) $(REGEX_HDRS)
LIBS = @LIBS@ $(W32_LIB) $(SOCKET_LIB) $(PTHREAD_LIB)
-const char actions_rcs[] = "$Id: actions.c,v 1.96 2016/02/26 12:29:38 fabiankeil Exp $";
+const char actions_rcs[] = "$Id: actions.c,v 1.97 2016/05/03 13:20:37 fabiankeil Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/actions.c,v $
};
-static int load_one_actions_file(struct client_state *csp, int fileid);
+#ifndef FUZZ
+static
+#endif
+int load_one_actions_file(struct client_state *csp, int fileid);
/*********************************************************************
* Returns : 0 => Ok, everything else is an error.
*
*********************************************************************/
-static int load_one_actions_file(struct client_state *csp, int fileid)
+#ifndef FUZZ
+static
+#endif
+int load_one_actions_file(struct client_state *csp, int fileid)
{
/*
#ifndef ACTIONS_H_INCLUDED
#define ACTIONS_H_INCLUDED
-#define ACTIONS_H_VERSION "$Id: actions.h,v 1.23 2013/11/24 14:24:17 fabiankeil Exp $"
+#define ACTIONS_H_VERSION "$Id: actions.h,v 1.24 2013/11/24 14:27:27 fabiankeil Exp $"
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/actions.h,v $
extern jb_err get_action_token(char **line, char **name, char **value);
extern void unload_actions_file(void *file_data);
extern int load_action_files(struct client_state *csp);
+#ifdef FUZZ
+extern int load_one_actions_file(struct client_state *csp, int fileid);
+#endif
#ifdef FEATURE_GRACEFUL_TERMINATION
void unload_current_actions_file(void);
dnl Process this file with autoconf to produce a configure script.
dnl
-dnl $Id: configure.in,v 1.205 2016/09/24 16:16:55 ler762 Exp $
+dnl $Id: configure.in,v 1.206 2016/09/27 22:48:28 ler762 Exp $
dnl
dnl Written by and Copyright (C) 2001-2016 the
dnl Privoxy team. https://www.privoxy.org/
dnl AutoConf Initialization
dnl =================================================================
-AC_REVISION($Revision: 1.205 $)
+AC_REVISION($Revision: 1.206 $)
AC_INIT(jcc.c)
if test ! -f config.h.in; then
fi
AC_SUBST(FEATURE_CLIENT_TAGS_ONLY)
+AC_ARG_ENABLE(fuzz,
+[ --enable-fuzz Enable code that makes fuzzing more convenient],
+[if test $enableval = yes; then
+ FUZZ_ONLY=""
+ AC_DEFINE(FUZZ,1,[Define to make fuzzing more convenient.])
+ else
+ FUZZ_ONLY="#"
+fi])
+AC_SUBST(FUZZ_ONLY)
+
dnl pcre/pcrs is needed for CGI anyway, so
dnl the choice is only between static and
dnl dynamic:
-const char errlog_rcs[] = "$Id: errlog.c,v 1.125 2016/01/26 17:12:14 diem Exp $";
+const char errlog_rcs[] = "$Id: errlog.c,v 1.126 2016/02/26 12:29:38 fabiankeil Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/errlog.c,v $
*********************************************************************/
void set_debug_level(int debug_level)
{
+#ifdef FUZZ
+ if (LOG_LEVEL_STFU == debug_level)
+ {
+ debug = LOG_LEVEL_STFU;
+ }
+ if (LOG_LEVEL_STFU == debug)
+ {
+ return;
+ }
+#endif
+
debug = debug_level | LOG_LEVEL_MINIMUM;
}
#endif
)
{
+#ifdef FUZZ
+ if (debug == LOG_LEVEL_STFU)
+ {
+ return;
+ }
+#endif
if (loglevel == LOG_LEVEL_FATAL)
{
fatal_error("Fatal error. You're not supposed to"
#ifndef ERRLOG_H_INCLUDED
#define ERRLOG_H_INCLUDED
-#define ERRLOG_H_VERSION "$Id: errlog.h,v 1.29 2012/07/27 17:39:57 fabiankeil Exp $"
+#define ERRLOG_H_VERSION "$Id: errlog.h,v 1.30 2013/11/24 14:23:28 fabiankeil Exp $"
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/errlog.h,v $
#define LOG_LEVEL_CGI 0x0800 /* CGI / templates */
#define LOG_LEVEL_RECEIVED 0x8000
#define LOG_LEVEL_ACTIONS 0x10000
+#ifdef FUZZ
+/*
+ * Permanently disables logging through log_error().
+ * Useful to reduce pointless overhead when fuzzing
+ * without watching stdout.
+ */
+#define LOG_LEVEL_STFU 0x20000
+#endif
/* Following are always on: */
#define LOG_LEVEL_INFO 0x1000
-const char filters_rcs[] = "$Id: filters.c,v 1.201 2016/03/17 10:40:53 fabiankeil Exp $";
+const char filters_rcs[] = "$Id: filters.c,v 1.202 2016/05/25 10:50:55 fabiankeil Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/filters.c,v $
typedef char *(*filter_function_ptr)();
static filter_function_ptr get_filter_function(const struct client_state *csp);
-static jb_err remove_chunked_transfer_coding(char *buffer, size_t *size);
static jb_err prepare_for_filtering(struct client_state *csp);
static void apply_url_actions(struct current_action_spec *action,
struct http_request *http,
* or NULL in case something went wrong.
*
*********************************************************************/
+#ifdef FUZZ
+char *gif_deanimate_response(struct client_state *csp)
+#else
static char *gif_deanimate_response(struct client_state *csp)
+#endif
{
struct binbuffer *in, *out;
char *p;
* JB_ERR_PARSE otherwise
*
*********************************************************************/
+#ifdef FUZZ
+extern jb_err remove_chunked_transfer_coding(char *buffer, size_t *size)
+#else
static jb_err remove_chunked_transfer_coding(char *buffer, size_t *size)
+#endif
{
size_t newsize = 0;
unsigned int chunksize = 0;
char *from_p, *to_p;
const char *end_of_buffer = buffer + *size;
+ if (*size == 0)
+ {
+ log_error(LOG_LEVEL_FATAL, "Invalid chunked input. Buffer is empty.");
+ return JB_ERR_PARSE;
+ }
+
assert(buffer);
from_p = to_p = buffer;
#ifndef FILTERS_H_INCLUDED
#define FILTERS_H_INCLUDED
-#define FILTERS_H_VERSION "$Id: filters.h,v 1.46 2013/12/24 13:32:51 fabiankeil Exp $"
+#define FILTERS_H_VERSION "$Id: filters.h,v 1.47 2016/03/17 10:40:53 fabiankeil Exp $"
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/filters.h,v $
extern const char filters_rcs[];
extern const char filters_h_rcs[];
+#ifdef FUZZ
+extern char *gif_deanimate_response(struct client_state *csp);
+extern jb_err remove_chunked_transfer_coding(char *buffer, size_t *size);
+#endif
+
#endif /* ndef FILTERS_H_INCLUDED */
/*
--- /dev/null
+/*********************************************************************
+ *
+ * File : $Source:$
+ *
+ * Purpose : Fuzz-related functions for Privoxy.
+ *
+ * Copyright : Written by and Copyright (C) 2014-16 by
+ * Fabian Keil <fk@fabiankeil.de>
+ *
+ * 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 GNU General Public
+ * License for more details.
+ *
+ * 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.
+ *
+ *********************************************************************/
+
+
+#include "config.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "project.h"
+#include "filters.h"
+#include "loaders.h"
+#include "parsers.h"
+#include "miscutil.h"
+#include "errlog.h"
+#include "actions.h"
+#include "cgi.h"
+#include "loadcfg.h"
+#include "urlmatch.h"
+#include "filters.h"
+#include "jbsockets.h"
+#include "gateway.h"
+#include "jcc.h"
+#include "list.h"
+
+
+#ifdef FUZZ
+static int fuzz_action(struct client_state *csp, char *fuzz_input_file);
+static int fuzz_client_header(struct client_state *csp, char *fuzz_input_file);
+static int fuzz_deflate(struct client_state *csp, char *fuzz_input_file);
+static int fuzz_filter(struct client_state *csp, char *fuzz_input_file);
+static int fuzz_gif(struct client_state *csp, char *fuzz_input_file);
+static int fuzz_gzip(struct client_state *csp, char *fuzz_input_file);
+#ifdef FUZZ_SOCKS
+static int fuzz_socks(struct client_state *csp, char *fuzz_input_file);
+#endif
+static int fuzz_pcrs_substitute(struct client_state *csp, char *fuzz_input_file);
+static int fuzz_server_header(struct client_state *csp, char *fuzz_input_file);
+
+struct fuzz_mode
+{
+ const char *name;
+ const char *expected_input;
+ const int stdin_support;
+ int (* const handler)(struct client_state *csp, char *input_file);
+};
+
+static const struct fuzz_mode fuzz_modes[] = {
+ { "action", "Text to parse as action file.", 0, fuzz_action },
+ { "client-request", "Client request to parse. Currently incomplete", 1, fuzz_client_request },
+ { "client-header", "Client header to parse.", 1, fuzz_client_header },
+ { "chunked-transfer-encoding", "Chunk-encoded data to dechunk.", 1, fuzz_chunked_transfer_encoding },
+ { "deflate", "deflate-compressed data to decompress.", 1, fuzz_deflate },
+ { "filter", "Text to parse as filter file.", 0, fuzz_filter },
+ { "gif", "gif to deanimate.", 1, fuzz_gif },
+ { "gzip", "gzip-compressed data to decompress.", 1, fuzz_gzip },
+ { "pcrs-substitute", "A pcrs-substitute to compile. Not a whole pcrs job! Example: Bla $1 bla \x43 $3 blah.", 1, fuzz_pcrs_substitute },
+ { "server-header", "Server header to parse.", 1, fuzz_server_header },
+ { "server-response", "Server response to parse.", 1, fuzz_server_response },
+#ifdef FUZZ_SOCKS
+ { "socks", "A socks server response. Only reads from stdin!", 1, fuzz_socks },
+#endif
+};
+
+/*********************************************************************
+ *
+ * Function : load_fuzz_input_from_stdin
+ *
+ * Description : Loads stdin into a buffer.
+ *
+ * Parameters :
+ * 1 : csp = Used to store the data.
+ *
+ * Returns : JB_ERR_OK in case of success,
+ *
+ *********************************************************************/
+static jb_err load_fuzz_input_from_stdin(struct client_state *csp)
+{
+ static char buf[BUFFER_SIZE];
+ int ret;
+
+ while (0 < (ret = read_socket(0, buf, sizeof(buf))))
+ {
+ log_error(LOG_LEVEL_INFO,
+ "Got %d bytes from stdin: %E. They look like this: %N",
+ ret, ret, buf);
+
+ if (add_to_iob(csp->iob, csp->config->buffer_limit, buf, ret))
+ {
+ log_error(LOG_LEVEL_FATAL, "Failed to buffer them.");
+ }
+ }
+
+ log_error(LOG_LEVEL_INFO, "Read %d bytes from stdin",
+ csp->iob->eod -csp->iob->cur);
+
+ return JB_ERR_OK;
+}
+
+/*********************************************************************
+ *
+ * Function : load_fuzz_input_from_file
+ *
+ * Description : Loads file content into a buffer.
+ *
+ * Parameters :
+ * 1 : csp = Used to store the data.
+ * 2 : filename = Name of the file to be loaded.
+ *
+ * Returns : JB_ERR_OK in case of success,
+ *
+ *********************************************************************/
+static jb_err load_fuzz_input_from_file(struct client_state *csp, const char *filename)
+{
+ FILE *fp;
+ size_t length;
+ long ret;
+
+ fp = fopen(filename, "rb");
+ if (NULL == fp)
+ {
+ log_error(LOG_LEVEL_FATAL, "Failed to open %s: %E", filename);
+ }
+
+ /* Get file length */
+ if (fseek(fp, 0, SEEK_END))
+ {
+ log_error(LOG_LEVEL_FATAL,
+ "Unexpected error while fseek()ing to the end of %s: %E",
+ filename);
+ }
+ ret = ftell(fp);
+ if (-1 == ret)
+ {
+ log_error(LOG_LEVEL_FATAL,
+ "Unexpected ftell() error while loading %s: %E",
+ filename);
+ }
+ length = (size_t)ret;
+
+ /* Go back to the beginning. */
+ if (fseek(fp, 0, SEEK_SET))
+ {
+ log_error(LOG_LEVEL_FATAL,
+ "Unexpected error while fseek()ing to the beginning of %s: %E",
+ filename);
+ }
+
+ csp->iob->size = length + 1;
+
+ csp->iob->buf = malloc_or_die(csp->iob->size);
+ csp->iob->cur = csp->iob->buf;
+ csp->iob->eod = csp->iob->buf + length;
+
+ if (1 != fread(csp->iob->cur, length, 1, fp))
+ {
+ /*
+ * May theoretically happen if the file size changes between
+ * fseek() and fread() because it's edited in-place. Privoxy
+ * and common text editors don't do that, thus we just fail.
+ */
+ log_error(LOG_LEVEL_FATAL,
+ "Couldn't completely read file %s.", filename);
+ }
+ *csp->iob->eod = '\0';
+
+ fclose(fp);
+
+ return JB_ERR_OK;
+
+}
+
+/*********************************************************************
+ *
+ * Function : load_fuzz_input
+ *
+ * Description : Loads a file into a buffer. XXX: Reverse argument order
+ *
+ * Parameters :
+ * 1 : csp = Used to store the data.
+ * 2 : filename = Name of the file to be loaded.
+ *
+ * Returns : JB_ERR_OK in case of success,
+ *
+ *********************************************************************/
+jb_err load_fuzz_input(struct client_state *csp, const char *filename)
+{
+ if (strcmp(filename, "-") == 0)
+ {
+ return load_fuzz_input_from_stdin(csp);
+ }
+
+ return load_fuzz_input_from_file(csp, filename);
+}
+
+
+/*********************************************************************
+ *
+ * Function : remove_forbidden_bytes
+ *
+ * Description : Sanitizes fuzzed data to decrease the likelihood of
+ * premature parse abortions.
+ *
+ * Parameters :
+ * 1 : csp = Used to store the data.
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+static void remove_forbidden_bytes(struct client_state *csp)
+{
+ char *p = csp->iob->cur;
+ char first_valid_byte = ' ';
+
+ while (p < csp->iob->eod)
+ {
+ if (*p != '\0')
+ {
+ first_valid_byte = *p;
+ break;
+ }
+ p++;
+ }
+
+ p = csp->iob->cur;
+ while (p < csp->iob->eod)
+ {
+ if (*p == '\0')
+ {
+ *p = first_valid_byte;
+ }
+ p++;
+ }
+}
+
+
+/*********************************************************************
+ *
+ * Function : fuzz_action
+ *
+ * Description : Treat the fuzzed input as action file.
+ *
+ * Parameters :
+ * 1 : csp = Used to store the data.
+ * 2 : fuzz_input_file = File to read the input from.
+ *
+ * Returns : Result of fuzzed function
+ *
+ *********************************************************************/
+int fuzz_action(struct client_state *csp, char *fuzz_input_file)
+{
+ csp->config->actions_file[0] = fuzz_input_file;
+
+ return(load_action_files(csp));
+}
+
+
+/*********************************************************************
+ *
+ * Function : fuzz_client_header
+ *
+ * Description : Treat the fuzzed input as a client header.
+ *
+ * Parameters :
+ * 1 : csp = Used to store the data.
+ * 2 : fuzz_input_file = File to read the input from.
+ *
+ * Returns : Result of fuzzed function
+ *
+ *********************************************************************/
+int fuzz_client_header(struct client_state *csp, char *fuzz_input_file)
+{
+ char *header;
+
+ header = get_header(csp->iob);
+
+ if (NULL == header)
+ {
+ return 1;
+ }
+ if (JB_ERR_OK != enlist(csp->headers, header))
+ {
+ return 1;
+ }
+
+ /*
+ * Silence an insightful client_host_adder() warning
+ * about ignored weirdness.
+ */
+ csp->flags |= CSP_FLAG_HOST_HEADER_IS_SET;
+ /* Adding headers doesn't depend on the fuzzed input */
+ csp->flags |= CSP_FLAG_CLIENT_CONNECTION_HEADER_SET;
+
+ /* +hide-if-modified-since{+60} */
+ csp->action->flags |= ACTION_HIDE_IF_MODIFIED_SINCE;
+ csp->action->string[ACTION_STRING_IF_MODIFIED_SINCE] = "+60";
+
+ /* XXX: Enable more actions. */
+
+ return(sed(csp, FILTER_CLIENT_HEADERS));
+}
+
+
+/*********************************************************************
+ *
+ * Function : fuzz_filter
+ *
+ * Description : Treat the fuzzed input as filter file.
+ *
+ * Parameters :
+ * 1 : csp = Used to store the data.
+ * 2 : fuzz_input_file = File to read the input from.
+ *
+ * Returns : Result of fuzzed function
+ *
+ *********************************************************************/
+int fuzz_filter(struct client_state *csp, char *fuzz_input_file)
+{
+ csp->config->re_filterfile[0] = fuzz_input_file;
+ return (load_one_re_filterfile(csp, 0));
+}
+
+
+/*********************************************************************
+ *
+ * Function : fuzz_deflate
+ *
+ * Description : Treat the fuzzed input as data to deflate.
+ *
+ * Parameters :
+ * 1 : csp = Used to store the data.
+ * 2 : fuzz_input_file = File to read the input from.
+ *
+ * Returns : Result of fuzzed function
+ *
+ *********************************************************************/
+static int fuzz_deflate(struct client_state *csp, char *fuzz_input_file)
+{
+ csp->content_type = CT_DEFLATE;
+ return(JB_ERR_OK == decompress_iob(csp));
+}
+
+
+/*********************************************************************
+ *
+ * Function : fuzz_gif
+ *
+ * Description : Treat the fuzzed input as a gif to deanimate.
+ *
+ * Parameters :
+ * 1 : csp = Used to store the data.
+ * 2 : fuzz_input_file = File to read the input from.
+ *
+ * Returns : Result of fuzzed function
+ *
+ *********************************************************************/
+static int fuzz_gif(struct client_state *csp, char *fuzz_input_file)
+{
+ char *deanimated_gif;
+
+ if (6 < csp->iob->size)
+ {
+ /* Why yes of course, officer, this is a gif. */
+ memcpy(csp->iob->cur, "GIF87a", 6);
+ }
+
+ /* Using the last image requires parsing of all images */
+ csp->action->string[ACTION_STRING_DEANIMATE] = "last";
+ deanimated_gif = gif_deanimate_response(csp);
+ if (NULL != deanimated_gif)
+ {
+ free(deanimated_gif);
+ return 0;
+ }
+
+ return 1;
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : fuzz_gzip
+ *
+ * Description : Treat the fuzzed input as data to unzip
+ *
+ * Parameters :
+ * 1 : csp = Used to store the data.
+ * 2 : fuzz_input_file = File to read the input from.
+ *
+ * Returns : Result of fuzzed function
+ *
+ *********************************************************************/
+static int fuzz_gzip(struct client_state *csp, char *fuzz_input_file)
+{
+ csp->content_type = CT_GZIP;
+
+ return(JB_ERR_OK == decompress_iob(csp));
+
+}
+
+
+#ifdef FUZZ_SOCKS
+/*********************************************************************
+ *
+ * Function : fuzz_socks
+ *
+ * Description : Treat the fuzzed input as a socks response.
+ * XXX: This is pretty useless as parsing socks repsonse
+ * is trivial.
+ *
+ * Parameters :
+ * 1 : csp = Used to store the data.
+ * 2 : fuzz_input_file = File to read the input from.
+ *
+ * Returns : Result of fuzzed function
+ *
+ *********************************************************************/
+static int fuzz_socks(struct client_state *csp, char *fuzz_input_file)
+{
+ return(JB_ERR_OK == socks_fuzz(csp));
+}
+#endif
+
+
+/*********************************************************************
+ *
+ * Function : fuzz_pcrs_substitute
+ *
+ * Description : Treat the fuzzed input as a pcrs substitute.
+ *
+ * Parameters :
+ * 1 : csp = Used to store the data.
+ * 2 : fuzz_input_file = File to read the input from.
+ *
+ * Returns : Result of fuzzed function
+ *
+ *********************************************************************/
+static int fuzz_pcrs_substitute(struct client_state *csp, char *fuzz_input_file)
+{
+ static pcrs_substitute *result;
+ int err;
+
+ remove_forbidden_bytes(csp);
+ result = pcrs_compile_fuzzed_replacement(csp->iob->cur, &err);
+ if (NULL == result)
+ {
+ log_error(LOG_LEVEL_ERROR,
+ "Failed to compile pcrs replacement. Error: %s", pcrs_strerror(err));
+ return 1;
+ }
+ log_error(LOG_LEVEL_INFO, "%s", pcrs_strerror(err));
+ free(result->text);
+ freez(result);
+ return 0;
+}
+
+
+/*********************************************************************
+ *
+ * Function : fuzz_server_header
+ *
+ * Description : Treat the fuzzed input as a server header.
+ *
+ * Parameters :
+ * 1 : csp = Used to store the data.
+ * 2 : fuzz_input_file = File to read the input from.
+ *
+ * Returns : Result of fuzzed function
+ *
+ *********************************************************************/
+int fuzz_server_header(struct client_state *csp, char *fuzz_input_file)
+{
+ char *header;
+
+ header = get_header(csp->iob);
+
+ if (NULL == header)
+ {
+ return 1;
+ }
+ if (JB_ERR_OK != enlist(csp->headers, header))
+ {
+ return 1;
+ }
+
+ /* Adding headers doesn't depend on the fuzzed input */
+ csp->flags |= CSP_FLAG_CLIENT_HEADER_PARSING_DONE;
+ csp->flags |= CSP_FLAG_SERVER_CONNECTION_HEADER_SET;
+
+ /* +overwrite-last-modified{randomize} */
+ csp->action->flags |= ACTION_OVERWRITE_LAST_MODIFIED;
+ csp->action->string[ACTION_STRING_LAST_MODIFIED] = "randomize";
+
+ /* +limit-cookie-lifetime{60} */
+ csp->action->flags |= ACTION_LIMIT_COOKIE_LIFETIME;
+ csp->action->string[ACTION_STRING_LIMIT_COOKIE_LIFETIME] = "60";
+
+ /* XXX: Enable more actions. */
+
+ return(sed(csp, FILTER_SERVER_HEADERS));
+}
+
+/*********************************************************************
+ *
+ * Function : process_fuzzed_input
+ *
+ * Description : Process the fuzzed input in a specified file treating
+ * it like the input type specified.
+ *
+ * XXX: Does not check malloc succcess.
+ *
+ * Parameters :
+ * 1 : fuzz_input_type = Type of input.
+ * 2 : fuzz_input_file = File to read the input from.
+ *
+ * Returns : Return value of the fuzzed function
+ *
+ *********************************************************************/
+int process_fuzzed_input(char *fuzz_input_type, char *fuzz_input_file)
+{
+ static struct client_state csp_stack_storage;
+ static struct configuration_spec config_stack_storage;
+ struct client_state *csp;
+ int i;
+
+ csp = &csp_stack_storage;
+ csp->config = &config_stack_storage;
+ csp->config->buffer_limit = 4096 * 1024;
+ /* In --stfu mode, these will be ignored ... */
+ set_debug_level(LOG_LEVEL_ACTIONS|LOG_LEVEL_CONNECT|LOG_LEVEL_DEANIMATE|LOG_LEVEL_INFO|LOG_LEVEL_ERROR|LOG_LEVEL_RE_FILTER|LOG_LEVEL_HEADER|LOG_LEVEL_WRITING|LOG_LEVEL_RECEIVED);
+
+ csp->flags |= CSP_FLAG_FUZZED_INPUT;
+ csp->config->feature_flags |= RUNTIME_FEATURE_ACCEPT_INTERCEPTED_REQUESTS;
+
+#ifdef FEATURE_CLIENT_TAGS
+ csp->config->trust_x_forwarded_for = 1;
+#endif
+
+ for (i = 0; i < SZ(fuzz_modes); i++)
+ {
+ if (strcmp(fuzz_modes[i].name, fuzz_input_type) == 0)
+ {
+ if (fuzz_modes[i].stdin_support &&
+ (strcmp(fuzz_input_type, "client-request") != 0) &&
+ (strcmp(fuzz_input_type, "server-response") != 0) &&
+ (strcmp(fuzz_input_type, "socks") != 0))
+ {
+ load_fuzz_input(csp, fuzz_input_file);
+ }
+ return (fuzz_modes[i].handler(csp, fuzz_input_file));
+ }
+ }
+
+ log_error(LOG_LEVEL_FATAL,
+ "Unrecognized fuzz type %s for input file %s. You may need --help.",
+ fuzz_input_type, fuzz_input_file);
+
+ /* Not reached. */
+ return 1;
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : show_fuzz_usage
+ *
+ * Description : Shows the --fuzz usage. D'oh.
+ *
+ * Parameters : Pointer to argv[0] for identifying ourselves
+ *
+ * Returns : void
+ *
+ *********************************************************************/
+void show_fuzz_usage(const char *name)
+{
+ int i;
+
+ printf("%s%s --fuzz fuzz-mode ./path/to/fuzzed/input [--stfu]\n\n",
+ " ", name);
+
+ printf("Supported fuzz modes and the expected input:\n");
+ for (i = 0; i < SZ(fuzz_modes); i++)
+ {
+ printf(" %s: %s\n", fuzz_modes[i].name, fuzz_modes[i].expected_input);
+ }
+ printf("\n");
+
+ printf("The following fuzz modes read data from stdin if the 'file' is '-'\n");
+ for (i = 0; i < SZ(fuzz_modes); i++)
+ {
+ if (fuzz_modes[i].stdin_support)
+ {
+ printf(" %s\n", fuzz_modes[i].name);
+ }
+ }
+ printf("\n");
+}
+#endif
-const char gateway_rcs[] = "$Id: gateway.c,v 1.98 2016/10/25 10:45:56 fabiankeil Exp $";
+const char gateway_rcs[] = "$Id: gateway.c,v 1.99 2016/10/25 10:46:56 fabiankeil Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/gateway.c,v $
}
+#ifdef FUZZ_SOCKS
+/*********************************************************************
+ *
+ * Function : socks_fuzz
+ *
+ * Description : Wrapper around socks[45]_connect() used for fuzzing.
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : JB_ERR_OK or JB_ERR_PARSE
+ *
+ *********************************************************************/
+extern jb_err socks_fuzz(struct client_state *csp)
+{
+ jb_socket socket;
+ static struct forward_spec fwd;
+ char target_host[] = "fuzz.example.org";
+ int target_port = 12345;
+
+ fwd.gateway_host = strdup_or_die("fuzz.example.org");
+ fwd.gateway_port = 12345;
+
+ fwd.type = SOCKS_4A;
+ socket = socks4_connect(&fwd, target_host, target_port, csp);
+
+ if (JB_INVALID_SOCKET != socket)
+ {
+ fwd.type = SOCKS_5;
+ socket = socks5_connect(&fwd, target_host, target_port, csp);
+ }
+
+ if (JB_INVALID_SOCKET == socket)
+ {
+ log_error(LOG_LEVEL_ERROR, "%s", csp->error_message);
+ return JB_ERR_PARSE;
+ }
+
+ log_error(LOG_LEVEL_INFO, "Input looks like an acceptable socks response");
+
+ return JB_ERR_OK;
+
+}
+#endif
+
/*********************************************************************
*
* Function : socks4_connect
c->dstip[2] = (unsigned char)((web_server_addr >> 8) & 0xff);
c->dstip[3] = (unsigned char)((web_server_addr ) & 0xff);
+#ifdef FUZZ_SOCKS
+ sfd = 0;
+#else
/* pass the request to the socks server */
sfd = connect_to(fwd->gateway_host, fwd->gateway_port, csp);
err = 1;
close_socket(sfd);
}
- else if (read_socket(sfd, buf, sizeof(buf)) != sizeof(*s))
+ else
+#endif
+ if (read_socket(sfd, buf, sizeof(buf)) != sizeof(*s))
{
errstr = "SOCKS4 negotiation read failed.";
log_error(LOG_LEVEL_CONNECT, "socks4_connect: %s", errstr);
}
}
+
/*********************************************************************
*
* Function : socks5_connect
return(JB_INVALID_SOCKET);
}
+#ifdef FUZZ_SOCKS
+ sfd = 0;
+ if (!err && read_socket(sfd, sbuf, 2) != 2)
+#else
/* pass the request to the socks server */
sfd = connect_to(fwd->gateway_host, fwd->gateway_port, csp);
close_socket(sfd);
return(JB_INVALID_SOCKET);
}
-
if (!data_is_available(sfd, csp->config->socket_timeout))
{
if (socket_is_still_alive(sfd))
}
if (!err && read_socket(sfd, sbuf, sizeof(sbuf)) != 2)
+#endif
{
errstr = "SOCKS5 negotiation read failed";
err = 1;
cbuf[client_pos++] = (char)((target_port >> 8) & 0xff);
cbuf[client_pos++] = (char)((target_port ) & 0xff);
+#ifndef FUZZ_SOCKS
if (write_socket(sfd, cbuf, client_pos))
{
errstr = "SOCKS5 negotiation write failed";
clear_iob(csp->client_iob);
}
}
+#endif
server_size = read_socket(sfd, sbuf, SIZE_SOCKS5_REPLY_IPV4);
if (server_size != SIZE_SOCKS5_REPLY_IPV4)
#ifndef GATEWAY_H_INCLUDED
#define GATEWAY_H_INCLUDED
-#define GATEWAY_H_VERSION "$Id: gateway.h,v 1.22 2012/10/23 10:16:52 fabiankeil Exp $"
+#define GATEWAY_H_VERSION "$Id: gateway.h,v 1.23 2013/11/24 14:23:28 fabiankeil Exp $"
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/gateway.h,v $
const struct forward_spec *fwd);
#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
+#ifdef FUZZ
+extern jb_err socks_fuzz(struct client_state *csp);
+#endif
+
/*
* Revision control strings from this header and associated .c file
*/
-const char jbsockets_rcs[] = "$Id: jbsockets.c,v 1.137 2016/08/22 14:50:18 fabiankeil Exp $";
+const char jbsockets_rcs[] = "$Id: jbsockets.c,v 1.138 2016/09/27 22:48:28 ler762 Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/jbsockets.c,v $
return 0;
}
+#ifdef FUZZ
+ if (!daemon_mode && fd <= 3)
+ {
+ log_error(LOG_LEVEL_WRITING, "Pretending to write to socket %d: %N", fd, len, buf);
+ return 0;
+ }
+#endif
+
log_error(LOG_LEVEL_WRITING, "to socket %d: %N", fd, len, buf);
#if defined(_WIN32)
-const char jcc_rcs[] = "$Id: jcc.c,v 1.447 2016/09/27 22:48:28 ler762 Exp $";
+const char jcc_rcs[] = "$Id: jcc.c,v 1.448 2016/12/24 15:58:49 fabiankeil Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/jcc.c,v $
#define sleep(N) DosSleep(((N) * 100))
#endif
+#ifdef FUZZ
+int process_fuzzed_input(char *fuzz_input_type, char *fuzz_input_file);
+void show_fuzz_usage(const char *name);
+#endif
+
#ifdef MUTEX_LOCKS_AVAILABLE
/*
* XXX: Does the locking stuff really belong in this file?
do
{
- if (!data_is_available(csp->cfd, csp->config->socket_timeout))
+ if (
+#ifdef FUZZ
+ 0 == (csp->flags & CSP_FLAG_FUZZED_INPUT) &&
+#endif
+ !data_is_available(csp->cfd, csp->config->socket_timeout)
+ )
{
if (socket_is_still_alive(csp->cfd))
{
}
+#ifdef FUZZ
+/*********************************************************************
+ *
+ * Function : fuzz_chunked_transfer_encoding
+ *
+ * Description : Treat the fuzzed input as chunked transfer encoding
+ * to check and dechunk.
+ *
+ * Parameters :
+ * 1 : csp = Used to store the data.
+ * 2 : fuzz_input_file = File to read the input from.
+ *
+ * Returns : Result of dechunking
+ *
+ *********************************************************************/
+extern int fuzz_chunked_transfer_encoding(struct client_state *csp, char *fuzz_input_file)
+{
+ size_t length;
+ size_t size = (size_t)(csp->iob->eod - csp->iob->cur);
+ enum chunk_status status;
+
+ status = chunked_body_is_complete(csp->iob, &length);
+ if (CHUNK_STATUS_BODY_COMPLETE != status)
+ {
+ log_error(LOG_LEVEL_INFO, "Chunked body is incomplete or invalid");
+ }
+
+ return (JB_ERR_OK == remove_chunked_transfer_coding(csp->iob->cur, &size));
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : fuzz_client_request
+ *
+ * Description : Try to get a client request from the fuzzed input.
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ * 2 : fuzz_input_file = File to read the input from.
+ *
+ * Returns : Result of fuzzing.
+ *
+ *********************************************************************/
+extern int fuzz_client_request(struct client_state *csp, char *fuzz_input_file)
+{
+ jb_err err;
+
+ csp->cfd = 0;
+ csp->ip_addr_str = "fuzzer";
+
+ if (strcmp(fuzz_input_file, "-") != 0)
+ {
+ log_error(LOG_LEVEL_FATAL,
+ "Fuzzed client requests can currenty only be read from stdin (-).");
+ }
+ err = receive_client_request(csp);
+ if (err != JB_ERR_OK)
+ {
+ return 1;
+ }
+ err = parse_client_request(csp);
+ if (err != JB_ERR_OK)
+ {
+ return 1;
+ }
+
+ return 0;
+
+}
+#endif /* def FUZZ */
+
+
#ifdef FEATURE_FORCE_LOAD
/*********************************************************************
*
csp->server_connection.timestamp = time(NULL);
}
+
/*********************************************************************
*
* Function : chat
}
+#ifdef FUZZ
+/*********************************************************************
+ *
+ * Function : fuzz_server_response
+ *
+ * Description : Treat the input as a whole server response.
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ * 2 : fuzz_input_file = File to read the input from.
+ *
+ * Returns : 0
+ *
+ *********************************************************************/
+extern int fuzz_server_response(struct client_state *csp, char *fuzz_input_file)
+{
+ static struct forward_spec fwd; /* Zero'd due to being static */
+ csp->cfd = 0;
+
+ if (strcmp(fuzz_input_file, "-") == 0)
+ {
+ /* XXX: Doesn'T work yet. */
+ csp->server_connection.sfd = 0;
+ }
+ else
+ {
+ csp->server_connection.sfd = open(fuzz_input_file, O_RDONLY);
+ if (csp->server_connection.sfd == -1)
+ {
+ log_error(LOG_LEVEL_FATAL, "Failed to open %s: %E",
+ fuzz_input_file);
+ }
+ }
+ csp->content_type |= CT_GIF;
+ csp->action->flags |= ACTION_DEANIMATE;
+ csp->action->string[ACTION_STRING_DEANIMATE] = "last";
+
+ csp->http->path = strdup_or_die("/");
+ csp->http->host = strdup_or_die("fuzz.example.org");
+ csp->http->hostport = strdup_or_die("fuzz.example.org:80");
+ /* Prevent client socket monitoring */
+ csp->flags |= CSP_FLAG_PIPELINED_REQUEST_WAITING;
+ csp->flags |= CSP_FLAG_CHUNKED;
+
+ csp->config->feature_flags |= RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE;
+ csp->flags |= CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE;
+
+ csp->content_type |= CT_DECLARED|CT_GIF;
+
+ csp->config->socket_timeout = 0;
+
+ cgi_init_error_messages();
+
+ handle_established_connection(csp, &fwd);
+
+ return 0;
+}
+#endif
+
+
#ifdef FEATURE_CONNECTION_KEEP_ALIVE
/*********************************************************************
*
* Returns : No. ,-)
*
*********************************************************************/
-static void usage(const char *myname)
+static void usage(const char *name)
{
printf("Privoxy version " VERSION " (" HOME_PAGE_URL ")\n"
"Usage: %s [--config-test] "
#if defined(unix)
"[--no-daemon] [--pidfile pidfile] [--pre-chroot-nslookup hostname] [--user user[.group]] "
#endif /* defined(unix) */
- "[--version] [configfile]\n"
- "Aborting\n", myname);
+ "[--version] [configfile]\n",
+ name);
+
+#ifdef FUZZ
+ show_fuzz_usage(name);
+#endif
+
+ printf("Aborting\n");
exit(2);
#endif /* def MUTEX_LOCKS_AVAILABLE */
}
-
/*********************************************************************
*
* Function : main
int do_chroot = 0;
char *pre_chroot_nslookup_to_load_resolver = NULL;
#endif
+#ifdef FUZZ
+ char *fuzz_input_type = NULL;
+ char *fuzz_input_file = NULL;
+#endif
Argc = argc;
Argv = argv;
{
do_config_test = 1;
}
-
+#ifdef FUZZ
+ else if (strcmp(argv[argc_pos], "--fuzz") == 0)
+ {
+ argc_pos++;
+ if (argc < argc_pos + 2) usage(argv[0]);
+ fuzz_input_type = argv[argc_pos];
+ argc_pos++;
+ fuzz_input_file = argv[argc_pos];
+ }
+ else if (strcmp(argv[argc_pos], "--stfu") == 0)
+ {
+ set_debug_level(LOG_LEVEL_STFU);
+ }
+#endif
else if (argc_pos + 1 != argc)
{
/*
# endif /* def _WIN_CONSOLE */
#endif /* def _WIN32 */
+#ifdef FUZZ
+ if (fuzz_input_type != NULL)
+ {
+ exit(process_fuzzed_input(fuzz_input_type, fuzz_input_file));
+ }
+#endif
+
if (do_config_test)
{
exit(NULL == load_config());
#ifndef JCC_H_INCLUDED
#define JCC_H_INCLUDED
-#define JCC_H_VERSION "$Id: jcc.h,v 1.35 2014/06/02 06:22:21 fabiankeil Exp $"
+#define JCC_H_VERSION "$Id: jcc.h,v 1.36 2016/03/17 10:40:53 fabiankeil Exp $"
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/jcc.h,v $
extern const char jcc_rcs[];
extern const char jcc_h_rcs[];
+#ifdef FUZZ
+extern int fuzz_client_request(struct client_state *csp, char *fuzz_input_file);
+extern int fuzz_server_response(struct client_state *csp, char *fuzz_input_file);
+extern int fuzz_chunked_transfer_encoding(struct client_state *csp, char *fuzz_input_file);
+#endif
+
#endif /* ndef JCC_H_INCLUDED */
/*
-const char loaders_rcs[] = "$Id: loaders.c,v 1.104 2016/05/22 12:43:07 fabiankeil Exp $";
+const char loaders_rcs[] = "$Id: loaders.c,v 1.105 2016/05/25 10:50:55 fabiankeil Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/loaders.c,v $
static struct file_list *current_trustfile = NULL;
#endif /* def FEATURE_TRUST */
+#ifndef FUZZ
static int load_one_re_filterfile(struct client_state *csp, int fileid);
+#endif
static struct file_list *current_re_filterfile[MAX_AF_FILES] = {
NULL, NULL, NULL, NULL, NULL,
for (;;)
{
ch = getc(fp);
+
if (ch == EOF)
{
if (len > 0)
}
else if (ch == 0)
{
+ /* XXX: Why do we allow this anyway? */
*p = '\0';
*dest = buf;
return JB_ERR_OK;
#ifndef LOADERS_H_INCLUDED
#define LOADERS_H_INCLUDED
-#define LOADERS_H_VERSION "$Id: loaders.h,v 1.31 2013/11/06 16:27:37 fabiankeil Exp $"
+#define LOADERS_H_VERSION "$Id: loaders.h,v 1.32 2013/11/24 14:23:28 fabiankeil Exp $"
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/loaders.h,v $
extern short int MustReload;
extern int load_action_files(struct client_state *csp);
extern int load_re_filterfiles(struct client_state *csp);
+#ifdef FUZZ
+extern int load_one_re_filterfile(struct client_state *csp, int fileid);
+#endif
#ifdef FEATURE_TRUST
extern int load_trustfile(struct client_state *csp);
-const char parsers_rcs[] = "$Id: parsers.c,v 1.309 2016/04/30 10:28:36 fabiankeil Exp $";
+const char parsers_rcs[] = "$Id: parsers.c,v 1.310 2016/12/09 09:13:19 fabiankeil Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/parsers.c,v $
int status; /* return status of the inflate() call */
z_stream zstr; /* used by calls to zlib */
+#ifdef FUZZ
+ assert(csp->iob->cur - csp->iob->buf >= 0);
+ assert(csp->iob->eod - csp->iob->cur >= 0);
+#else
assert(csp->iob->cur - csp->iob->buf > 0);
assert(csp->iob->eod - csp->iob->cur > 0);
+#endif
bufsize = csp->iob->size;
skip_size = (size_t)(csp->iob->cur - csp->iob->buf);
* Make sure the new uncompressed iob obeys some minimal
* consistency conditions.
*/
- if ((csp->iob->buf < csp->iob->cur)
+ if ((csp->iob->buf <= csp->iob->cur)
&& (csp->iob->cur <= csp->iob->eod)
&& (csp->iob->eod <= csp->iob->buf + csp->iob->size))
{
-const char pcrs_rcs[] = "$Id: pcrs.c,v 1.49 2016/05/08 10:45:51 fabiankeil Exp $";
+const char pcrs_rcs[] = "$Id: pcrs.c,v 1.50 2016/05/25 10:50:28 fabiankeil Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/pcrs.c,v $
}
+#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
size_t length;
char *text;
pcrs_substitute *r;
-
+#ifdef FUZZ
+ static const char *replacement_stack;
+ static const size_t *length_stack;
+ static pcrs_substitute *r_stack;
+
+ replacement_stack = replacement;
+ length_stack = &length;
+#endif
i = k = l = quoted = 0;
/*
}
memset(r, '\0', sizeof(pcrs_substitute));
+#ifdef FUZZ
+ r_stack = r;
+#endif
+
length = strlen(replacement);
if (NULL == (text = (char *)malloc(length + 1)))
*
*********************************************************************/
-#define PCRS_H_VERSION "$Id: pcrs.h,v 1.17 2009/05/16 13:27:20 fabiankeil Exp $"
+#define PCRS_H_VERSION "$Id: pcrs.h,v 1.18 2013/11/24 14:23:28 fabiankeil Exp $"
#ifndef _PCRE_H
#define PCRS_BUFFER_SIZE 4000
#endif /* ndef PCRS_BUFFER_SIZE */
+#ifdef FUZZ
+extern pcrs_substitute *pcrs_compile_fuzzed_replacement(const char *replacement, int *errptr);
+#endif
+
#endif /* ndef PCRS_H_INCLUDED */
/*
#ifndef PROJECT_H_INCLUDED
#define PROJECT_H_INCLUDED
/** Version string. */
-#define PROJECT_H_VERSION "$Id: project.h,v 1.216 2016/05/25 10:50:55 fabiankeil Exp $"
+#define PROJECT_H_VERSION "$Id: project.h,v 1.217 2016/09/27 22:48:28 ler762 Exp $"
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/project.h,v $
*/
#define CSP_FLAG_CRUNCHED 0x04000000U
+#ifdef FUZZ
+/**
+ * Flag for csp->flags: Set if we are working with fuzzed input
+ */
+#define CSP_FLAG_FUZZED_INPUT 0x08000000U
+#endif
/*
* Flags for use in return codes of child processes
-const char urlmatch_rcs[] = "$Id: urlmatch.c,v 1.87 2016/02/26 12:29:39 fabiankeil Exp $";
+const char urlmatch_rcs[] = "$Id: urlmatch.c,v 1.88 2016/03/17 10:40:53 fabiankeil Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/urlmatch.c,v $
struct pattern_spec *url, regex_t **regex)
{
int errcode;
- char rebuf[BUFFER_SIZE];
const char *fmt = NULL;
+ char *rebuf;
+ size_t rebuf_size;
assert(pattern);
- assert(strlen(pattern) < sizeof(rebuf) - 2);
if (pattern[0] == '\0')
{
log_error(LOG_LEVEL_FATAL,
"Invalid anchoring in compile_pattern %d", anchoring);
}
-
+ rebuf_size = strlen(pattern) + strlen(fmt);
+ rebuf = malloc_or_die(rebuf_size);
*regex = zalloc_or_die(sizeof(**regex));
- snprintf(rebuf, sizeof(rebuf), fmt, pattern);
+ snprintf(rebuf, rebuf_size, fmt, pattern);
errcode = regcomp(*regex, rebuf, (REG_EXTENDED|REG_NOSUB|REG_ICASE));
if (errcode)
{
- size_t errlen = regerror(errcode, *regex, rebuf, sizeof(rebuf));
- if (errlen > (sizeof(rebuf) - (size_t)1))
+ size_t errlen = regerror(errcode, *regex, rebuf, rebuf_size);
+ if (errlen > (rebuf_size - (size_t)1))
{
- errlen = sizeof(rebuf) - (size_t)1;
+ errlen = rebuf_size - (size_t)1;
}
rebuf[errlen] = '\0';
log_error(LOG_LEVEL_ERROR, "error compiling %s from %s: %s",
pattern, url->spec, rebuf);
free_pattern_spec(url);
+ freez(rebuf);
return JB_ERR_PARSE;
}
+ freez(rebuf);
return JB_ERR_OK;