/*
* Copyright © 2021 Contrast Security, Inc.
* See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
*/
/* THIS FILE WAS AUTOMATICALLY GENERATED BY HOOKSPY */
/* Python requires its own header to always be included first */
#define PY_SSIZE_T_CLEAN
#include <Python.h>

#include <contrast/assess/propagate.h>
#include <contrast/assess/scope.h>
#include <contrast/assess/utils.h>

typedef PyObject *(*fastcall_func)(PyObject *, PyObject *const *, Py_ssize_t);
typedef PyObject *(*fastcall_kwargs_func)(PyObject *, PyObject *const *, Py_ssize_t, PyObject *);

#define BYTEARRAY_DECODE_OFFSET 10
#define BYTEARRAY_REPLACE_OFFSET 35
#define BYTEARRAY_SPLIT_OFFSET 43
#define BYTEARRAY_RSPLIT_OFFSET 41
#define BYTEARRAY_CAPITALIZE_OFFSET 5
#define BYTEARRAY_TITLE_OFFSET 48
#define BYTEARRAY_CENTER_OFFSET 6
#define BYTEARRAY_EXPANDTABS_OFFSET 12
#define BYTEARRAY_PARTITION_OFFSET 32
#define BYTEARRAY_LJUST_OFFSET 28
#define BYTEARRAY_LOWER_OFFSET 29
#define BYTEARRAY_LSTRIP_OFFSET 30
#define BYTEARRAY_RJUST_OFFSET 39
#define BYTEARRAY_RSTRIP_OFFSET 42
#define BYTEARRAY_RPARTITION_OFFSET 40
#define BYTEARRAY_SPLITLINES_OFFSET 44
#define BYTEARRAY_STRIP_OFFSET 46
#define BYTEARRAY_SWAPCASE_OFFSET 47
#define BYTEARRAY_TRANSLATE_OFFSET 49
#define BYTEARRAY_UPPER_OFFSET 50
#define BYTEARRAY_ZFILL_OFFSET 51


fastcall_kwargs_func bytearray_decode_orig;
fastcall_func bytearray_replace_orig;
fastcall_kwargs_func bytearray_split_orig;
fastcall_kwargs_func bytearray_rsplit_orig;
unaryfunc bytearray_capitalize_orig;
unaryfunc bytearray_title_orig;
binaryfunc bytearray_center_orig;
ternaryfunc bytearray_expandtabs_orig;
binaryfunc bytearray_partition_orig;
binaryfunc bytearray_ljust_orig;
unaryfunc bytearray_lower_orig;
fastcall_func bytearray_lstrip_orig;
binaryfunc bytearray_rjust_orig;
fastcall_func bytearray_rstrip_orig;
binaryfunc bytearray_rpartition_orig;
fastcall_kwargs_func bytearray_splitlines_orig;
fastcall_func bytearray_strip_orig;
unaryfunc bytearray_swapcase_orig;
fastcall_kwargs_func bytearray_translate_orig;
unaryfunc bytearray_upper_orig;
binaryfunc bytearray_zfill_orig;
initproc bytearray_init_orig;


HOOK_TERNARY_FASTCALL(bytearray_decode, "decode");
PyObject *bytearray_replace_new(PyObject *self, PyObject *const *args, Py_ssize_t nargs) {
    /* In Py37 the replace method type moved to METH_FASTARGS. This means that
     * instead of args being passed as a tuple, they are passed as a C array
     * that contains PyObjects. We need to check whether there is the number of
     * args that we expect, and whether the arg we care about is not NULL.
     * Specifically, we want args[1] since it represents the "new" string in
     * the replacement.
     */
    PyObject *hook_args = pack_args_tuple(args, nargs);
    PyObject *result = bytearray_replace_orig(self, args, nargs);

    if (result == NULL || nargs < 2 || args[1] == NULL)
        goto cleanup_and_exit;

    if (result == self)
        goto cleanup_and_exit;

    propagate_result("replace", self, result, hook_args, NULL);

cleanup_and_exit:
    Py_XDECREF(hook_args);
    return result;

}

PyObject *bytearray_split_new(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) {
    PyObject *result = bytearray_split_orig(self, args, nargs, kwnames);
    PyObject *args_tuple = pack_args_tuple(args, nargs);
    PyObject *kwargs = pack_kwargs_dict(args, nargs, kwnames);

    if (result == NULL || PySequence_Length(result) == 1)
        goto cleanup_and_exit;

    propagate_result("split", (PyObject *)self, result, args_tuple, kwargs);

cleanup_and_exit:
    Py_XDECREF(args_tuple);
    Py_XDECREF(kwargs);
    return result;

}

PyObject *bytearray_rsplit_new(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) {
    PyObject *result = bytearray_rsplit_orig(self, args, nargs, kwnames);
    PyObject *args_tuple = pack_args_tuple(args, nargs);
    PyObject *kwargs = pack_kwargs_dict(args, nargs, kwnames);

    if (result == NULL || PySequence_Length(result) == 1)
        goto cleanup_and_exit;

    propagate_result("rsplit", (PyObject *)self, result, args_tuple, kwargs);

cleanup_and_exit:
    Py_XDECREF(args_tuple);
    Py_XDECREF(kwargs);
    return result;

}

HOOK_UNARYFUNC(bytearray_capitalize, "capitalize");
HOOK_UNARYFUNC(bytearray_title, "title");
HOOK_BINARYFUNC(bytearray_center, "center");
HOOK_TERNARYFUNC(bytearray_expandtabs, "expandtabs");
HOOK_BINARYFUNC(bytearray_partition, "partition");
HOOK_BINARYFUNC(bytearray_ljust, "ljust");
HOOK_UNARYFUNC(bytearray_lower, "lower");
HOOK_FASTCALL(bytearray_lstrip, "lstrip");
HOOK_BINARYFUNC(bytearray_rjust, "rjust");
HOOK_FASTCALL(bytearray_rstrip, "rstrip");
HOOK_BINARYFUNC(bytearray_rpartition, "rpartition");
HOOK_TERNARY_FASTCALL(bytearray_splitlines, "splitlines");
HOOK_FASTCALL(bytearray_strip, "strip");
HOOK_UNARYFUNC(bytearray_swapcase, "swapcase");
HOOK_TERNARY_FASTCALL(bytearray_translate, "translate");
HOOK_UNARYFUNC(bytearray_upper, "upper");
HOOK_BINARYFUNC(bytearray_zfill, "zfill");
int bytearray_init_new(PyObject *self, PyObject *args, PyObject *kwds) {
    int result = bytearray_init_orig(self, args, kwds);

    if (result == -1)
        return result;

    /* Here we report self_obj=None and ret=self
       to maintain the illusion of casting */
    propagate_result("CAST", NULL, self, args, kwds);

    return result;

}




int apply_bytearray_patches(funchook_t *funchook) {

    ADD_METHOD_HOOK(PyByteArray_Type, bytearray_decode, BYTEARRAY_DECODE_OFFSET);
    ADD_METHOD_HOOK(PyByteArray_Type, bytearray_replace, BYTEARRAY_REPLACE_OFFSET);
    ADD_METHOD_HOOK(PyByteArray_Type, bytearray_split, BYTEARRAY_SPLIT_OFFSET);
    ADD_METHOD_HOOK(PyByteArray_Type, bytearray_rsplit, BYTEARRAY_RSPLIT_OFFSET);
    /* bytearray.join hook is not included because it is buggy */
    ADD_METHOD_HOOK(PyByteArray_Type, bytearray_capitalize, BYTEARRAY_CAPITALIZE_OFFSET);
    ADD_METHOD_HOOK(PyByteArray_Type, bytearray_title, BYTEARRAY_TITLE_OFFSET);
    ADD_METHOD_HOOK(PyByteArray_Type, bytearray_center, BYTEARRAY_CENTER_OFFSET);
    ADD_METHOD_HOOK(PyByteArray_Type, bytearray_expandtabs, BYTEARRAY_EXPANDTABS_OFFSET);
    ADD_METHOD_HOOK(PyByteArray_Type, bytearray_partition, BYTEARRAY_PARTITION_OFFSET);
    ADD_METHOD_HOOK(PyByteArray_Type, bytearray_ljust, BYTEARRAY_LJUST_OFFSET);
    ADD_METHOD_HOOK(PyByteArray_Type, bytearray_lower, BYTEARRAY_LOWER_OFFSET);
    ADD_METHOD_HOOK(PyByteArray_Type, bytearray_lstrip, BYTEARRAY_LSTRIP_OFFSET);
    ADD_METHOD_HOOK(PyByteArray_Type, bytearray_rjust, BYTEARRAY_RJUST_OFFSET);
    ADD_METHOD_HOOK(PyByteArray_Type, bytearray_rstrip, BYTEARRAY_RSTRIP_OFFSET);
    ADD_METHOD_HOOK(PyByteArray_Type, bytearray_rpartition, BYTEARRAY_RPARTITION_OFFSET);
    ADD_METHOD_HOOK(PyByteArray_Type, bytearray_splitlines, BYTEARRAY_SPLITLINES_OFFSET);
    ADD_METHOD_HOOK(PyByteArray_Type, bytearray_strip, BYTEARRAY_STRIP_OFFSET);
    ADD_METHOD_HOOK(PyByteArray_Type, bytearray_swapcase, BYTEARRAY_SWAPCASE_OFFSET);
    ADD_METHOD_HOOK(PyByteArray_Type, bytearray_translate, BYTEARRAY_TRANSLATE_OFFSET);
    ADD_METHOD_HOOK(PyByteArray_Type, bytearray_upper, BYTEARRAY_UPPER_OFFSET);
    ADD_METHOD_HOOK(PyByteArray_Type, bytearray_zfill, BYTEARRAY_ZFILL_OFFSET);
    ADD_INITPROC_HOOK(PyByteArray_Type, bytearray_init);

    /* Indicates success */
    return 0;
}

