view contrib/fuzz/jsonescapeu8fast.cc @ 43325:7d4f2e4899c5 stable

py3: fix headencode() with display=False We previously called str() on a email.header.Header object. On Python 2, this returns a bytestring and the __str__ method is actually an alias to .encode() method. On Python 3, __str__ does not perform encoding (and returns a unicode string). To keep a consistent behavior across Python versions, we explicitly use .encode() and we wrap the result with encoding.strtolocal() to get a bytestring in all cases. As a side effect of forcing bytes conversion, we need to decode back in _addressencode(). This is to make test-notify.t pass on Python 3. Also note that headers are now encoded in some patchbomb tests; this is because the charset is not always "us-ascii" ("iso-8859-1" otherwise) on Python 3.
author Denis Laxalde <denis.laxalde@logilab.fr>
date Thu, 24 Oct 2019 17:16:43 +0200
parents 741fb1a95da2
children 5a9e2ae9899b
line wrap: on
line source

#include <Python.h>
#include <assert.h>
#include <stdlib.h>
#include <unistd.h>

#include "pyutil.h"

#include <fuzzer/FuzzedDataProvider.h>
#include <iostream>
#include <string>

extern "C" {

static PyCodeObject *code;

extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv)
{
	contrib::initpy(*argv[0]);
	code = (PyCodeObject *)Py_CompileString(R"py(
from parsers import jsonescapeu8fast

try:
    jsonescapeu8fast(data, paranoid)
except Exception as e:
    pass
    # uncomment this print if you're editing this Python code
    # to debug failures.
    # print(e)
)py",
	                                        "fuzzer", Py_file_input);
	if (!code) {
		std::cerr << "failed to compile Python code!" << std::endl;
	}
	return 0;
}

int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size)
{
	FuzzedDataProvider provider(Data, Size);
	bool paranoid = provider.ConsumeBool();
	std::string remainder = provider.ConsumeRemainingBytesAsString();

	PyObject *mtext = PyBytes_FromStringAndSize(
	    (const char *)remainder.c_str(), remainder.size());
	PyObject *locals = PyDict_New();
	PyDict_SetItemString(locals, "data", mtext);
	PyDict_SetItemString(locals, "paranoid", paranoid ? Py_True : Py_False);
	PyObject *res = PyEval_EvalCode(code, contrib::pyglobals(), locals);
	if (!res) {
		PyErr_Print();
	}
	Py_XDECREF(res);
	Py_DECREF(locals);
	Py_DECREF(mtext);
	return 0; // Non-zero return values are reserved for future use.
}
}