Staging
v0.8.1
Revision 070fae6d0ff49e63bfd5f2bdc66f8eb1df3b6557 authored by Christian Heimes on 02 July 2019, 18:39:42 UTC, committed by Ned Deily on 02 July 2019, 18:42:08 UTC


ssl.match_hostname() no longer accepts IPv4 addresses with additional text
after the address and only quad-dotted notation without trailing
whitespaces. Some inet_aton() implementations ignore whitespace and all data
after whitespace, e.g. '127.0.0.1 whatever'.

Short notations like '127.1' for '127.0.0.1' were already filtered out.

The bug was initially found by Dominik Czarnota and reported by Paul Kehrer.

Signed-off-by: Christian Heimes <christian@python.org>



https://bugs.python.org/issue37463
1 parent dcc0eb3
Raw File
namespaceobject.c
// namespace object implementation

#include "Python.h"
#include "structmember.h"


typedef struct {
    PyObject_HEAD
    PyObject *ns_dict;
} _PyNamespaceObject;


static PyMemberDef namespace_members[] = {
    {"__dict__", T_OBJECT, offsetof(_PyNamespaceObject, ns_dict), READONLY},
    {NULL}
};


// Methods

static PyObject *
namespace_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
    PyObject *self;

    assert(type != NULL && type->tp_alloc != NULL);
    self = type->tp_alloc(type, 0);
    if (self != NULL) {
        _PyNamespaceObject *ns = (_PyNamespaceObject *)self;
        ns->ns_dict = PyDict_New();
        if (ns->ns_dict == NULL) {
            Py_DECREF(ns);
            return NULL;
        }
    }
    return self;
}


static int
namespace_init(_PyNamespaceObject *ns, PyObject *args, PyObject *kwds)
{
    if (PyTuple_GET_SIZE(args) != 0) {
        PyErr_Format(PyExc_TypeError, "no positional arguments expected");
        return -1;
    }
    if (kwds == NULL) {
        return 0;
    }
    if (!PyArg_ValidateKeywordArguments(kwds)) {
        return -1;
    }
    return PyDict_Update(ns->ns_dict, kwds);
}


static void
namespace_dealloc(_PyNamespaceObject *ns)
{
    PyObject_GC_UnTrack(ns);
    Py_CLEAR(ns->ns_dict);
    Py_TYPE(ns)->tp_free((PyObject *)ns);
}


static PyObject *
namespace_repr(PyObject *ns)
{
    int i, loop_error = 0;
    PyObject *pairs = NULL, *d = NULL, *keys = NULL, *keys_iter = NULL;
    PyObject *key;
    PyObject *separator, *pairsrepr, *repr = NULL;
    const char * name;

    name = (Py_TYPE(ns) == &_PyNamespace_Type) ? "namespace"
                                               : ns->ob_type->tp_name;

    i = Py_ReprEnter(ns);
    if (i != 0) {
        return i > 0 ? PyUnicode_FromFormat("%s(...)", name) : NULL;
    }

    pairs = PyList_New(0);
    if (pairs == NULL)
        goto error;

    d = ((_PyNamespaceObject *)ns)->ns_dict;
    assert(d != NULL);
    Py_INCREF(d);

    keys = PyDict_Keys(d);
    if (keys == NULL)
        goto error;
    if (PyList_Sort(keys) != 0)
        goto error;

    keys_iter = PyObject_GetIter(keys);
    if (keys_iter == NULL)
        goto error;

    while ((key = PyIter_Next(keys_iter)) != NULL) {
        if (PyUnicode_Check(key) && PyUnicode_GET_LENGTH(key) > 0) {
            PyObject *value, *item;

            value = PyDict_GetItem(d, key);
            if (value != NULL) {
                item = PyUnicode_FromFormat("%S=%R", key, value);
                if (item == NULL) {
                    loop_error = 1;
                }
                else {
                    loop_error = PyList_Append(pairs, item);
                    Py_DECREF(item);
                }
            }
        }

        Py_DECREF(key);
        if (loop_error)
            goto error;
    }

    separator = PyUnicode_FromString(", ");
    if (separator == NULL)
        goto error;

    pairsrepr = PyUnicode_Join(separator, pairs);
    Py_DECREF(separator);
    if (pairsrepr == NULL)
        goto error;

    repr = PyUnicode_FromFormat("%s(%S)", name, pairsrepr);
    Py_DECREF(pairsrepr);

error:
    Py_XDECREF(pairs);
    Py_XDECREF(d);
    Py_XDECREF(keys);
    Py_XDECREF(keys_iter);
    Py_ReprLeave(ns);

    return repr;
}


static int
namespace_traverse(_PyNamespaceObject *ns, visitproc visit, void *arg)
{
    Py_VISIT(ns->ns_dict);
    return 0;
}


static int
namespace_clear(_PyNamespaceObject *ns)
{
    Py_CLEAR(ns->ns_dict);
    return 0;
}


static PyObject *
namespace_richcompare(PyObject *self, PyObject *other, int op)
{
    if (PyObject_TypeCheck(self, &_PyNamespace_Type) &&
        PyObject_TypeCheck(other, &_PyNamespace_Type))
        return PyObject_RichCompare(((_PyNamespaceObject *)self)->ns_dict,
                                   ((_PyNamespaceObject *)other)->ns_dict, op);
    Py_RETURN_NOTIMPLEMENTED;
}


PyDoc_STRVAR(namespace_reduce__doc__, "Return state information for pickling");

static PyObject *
namespace_reduce(_PyNamespaceObject *ns)
{
    PyObject *result, *args = PyTuple_New(0);

    if (!args)
        return NULL;

    result = PyTuple_Pack(3, (PyObject *)Py_TYPE(ns), args, ns->ns_dict);
    Py_DECREF(args);
    return result;
}


static PyMethodDef namespace_methods[] = {
    {"__reduce__", (PyCFunction)namespace_reduce, METH_NOARGS,
     namespace_reduce__doc__},
    {NULL,         NULL}  // sentinel
};


PyDoc_STRVAR(namespace_doc,
"A simple attribute-based namespace.\n\
\n\
SimpleNamespace(**kwargs)");

PyTypeObject _PyNamespace_Type = {
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
    "types.SimpleNamespace",                    /* tp_name */
    sizeof(_PyNamespaceObject),                 /* tp_basicsize */
    0,                                          /* tp_itemsize */
    (destructor)namespace_dealloc,              /* tp_dealloc */
    0,                                          /* tp_print */
    0,                                          /* tp_getattr */
    0,                                          /* tp_setattr */
    0,                                          /* tp_reserved */
    (reprfunc)namespace_repr,                   /* tp_repr */
    0,                                          /* tp_as_number */
    0,                                          /* tp_as_sequence */
    0,                                          /* tp_as_mapping */
    0,                                          /* tp_hash */
    0,                                          /* tp_call */
    0,                                          /* tp_str */
    PyObject_GenericGetAttr,                    /* tp_getattro */
    PyObject_GenericSetAttr,                    /* tp_setattro */
    0,                                          /* tp_as_buffer */
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
        Py_TPFLAGS_BASETYPE,                    /* tp_flags */
    namespace_doc,                              /* tp_doc */
    (traverseproc)namespace_traverse,           /* tp_traverse */
    (inquiry)namespace_clear,                   /* tp_clear */
    namespace_richcompare,                      /* tp_richcompare */
    0,                                          /* tp_weaklistoffset */
    0,                                          /* tp_iter */
    0,                                          /* tp_iternext */
    namespace_methods,                          /* tp_methods */
    namespace_members,                          /* tp_members */
    0,                                          /* tp_getset */
    0,                                          /* tp_base */
    0,                                          /* tp_dict */
    0,                                          /* tp_descr_get */
    0,                                          /* tp_descr_set */
    offsetof(_PyNamespaceObject, ns_dict),      /* tp_dictoffset */
    (initproc)namespace_init,                   /* tp_init */
    PyType_GenericAlloc,                        /* tp_alloc */
    (newfunc)namespace_new,                     /* tp_new */
    PyObject_GC_Del,                            /* tp_free */
};


PyObject *
_PyNamespace_New(PyObject *kwds)
{
    PyObject *ns = namespace_new(&_PyNamespace_Type, NULL, NULL);
    if (ns == NULL)
        return NULL;

    if (kwds == NULL)
        return ns;
    if (PyDict_Update(((_PyNamespaceObject *)ns)->ns_dict, kwds) != 0) {
        Py_DECREF(ns);
        return NULL;
    }

    return (PyObject *)ns;
}
back to top