Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Memory corruption due to size expansion (overflow) in _json.encode_basestring_ascii on 32 bit Python 2.7.12 #72471

Closed
benjaminp opened this issue Sep 27, 2016 · 2 comments
Labels
type-security A security issue

Comments

@benjaminp
Copy link
Contributor

BPO 28284
Nosy @benjaminp

Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

Show more details

GitHub fields:

assignee = None
closed_at = <Date 2016-09-27.06:55:49.693>
created_at = <Date 2016-09-27.06:54:57.874>
labels = ['type-security']
title = 'Memory corruption due to size expansion (overflow) in _json.encode_basestring_ascii on 32 bit Python 2.7.12'
updated_at = <Date 2016-09-27.06:55:49.692>
user = 'https://github.com/benjaminp'

bugs.python.org fields:

activity = <Date 2016-09-27.06:55:49.692>
actor = 'python-dev'
assignee = 'none'
closed = True
closed_date = <Date 2016-09-27.06:55:49.693>
closer = 'python-dev'
components = []
creation = <Date 2016-09-27.06:54:57.874>
creator = 'benjamin.peterson'
dependencies = []
files = []
hgrepos = []
issue_num = 28284
keywords = []
message_count = 2.0
messages = ['277494', '277495']
nosy_count = 2.0
nosy_names = ['benjamin.peterson', 'python-dev']
pr_nums = []
priority = 'normal'
resolution = 'fixed'
stage = 'resolved'
status = 'closed'
superseder = None
type = 'security'
url = 'https://bugs.python.org/issue28284'
versions = ['Python 2.7']

@benjaminp
Copy link
Contributor Author

Guido Vranken reports:

This results in a segmentation fault on 32 bit:

python -c "import _json; print
_json.encode_basestring_ascii(unicode(chr(0x22)) * 0x2AAAAAAB)"

This is a tentative patch:

diff --git a/Modules/_json.c b/Modules/_json.c
index fede6b1..022bbc8 100644
--- a/Modules/_json.c
+++ b/Modules/_json.c
@@ -212,7 +212,16 @@ ascii_escape_unicode(PyObject *pystr)

     /* One char input can be up to 6 chars output, estimate 4 of these */
     output_size = 2 + (MIN_EXPANSION * 4) + input_chars;
-    max_output_size = 2 + (input_chars * MAX_EXPANSION);
+    if (input_chars > (PY_SSIZE_T_MAX / MAX_EXPANSION) ) {
+        PyErr_SetString(PyExc_ValueError, "Size of escaped string
exceeds upper boundary");
+        return NULL;
+    }
+    max_output_size = (input_chars * MAX_EXPANSION);
+    if ( max_output_size > (PY_SSIZE_T_MAX - 2)) {
+        PyErr_SetString(PyExc_ValueError, "Size of escaped string
exceeds upper boundary");
+        return NULL;
+    }
+    max_output_size += 2;
     rval = PyString_FromStringAndSize(NULL, output_size);
     if (rval == NULL) {
         return NULL;

But you still have to take account these things:

            /* This is an upper bound */
            if (new_output_size > max_output_size) {
                new_output_size = max_output_size;
            }

If this code within the if{} is reached then it merely truncates the
amount of memory that is actually required, thereby creating another
opportunity for overwrites?

And this:

            Py_ssize_t new_output_size = output_size * 2;

might overflow, but since output_size is always positive (ie. in the
range [0..PY_SSIZE_T_MAX]), an overflow would result in a negative
value. That would subsequently be caught in _PyString_Resize():

int
_PyString_Resize(PyObject **pv, Py_ssize_t newsize)
{
    register PyObject *v;
    register PyStringObject *sv;
    v = *pv;
    if (!PyString_Check(v) || Py_REFCNT(v) != 1 || newsize < 0 ||
        PyString_CHECK_INTERNED(v)) {
        *pv = 0;
        Py_DECREF(v);
        PyErr_BadInternalCall();
        return -1;
    }

Nonetheless an overflow from positive to negative is undesirable (it's
undefined behaviour).

@benjaminp benjaminp added the type-security A security issue label Sep 27, 2016
@python-dev
Copy link
Mannequin

python-dev mannequin commented Sep 27, 2016

New changeset 9375c8834448 by Benjamin Peterson in branch '2.7':
be extremely careful about overflows in encode_basestring_ascii (closes bpo-28284)
https://hg.python.org/cpython/rev/9375c8834448

@python-dev python-dev mannequin closed this as completed Sep 27, 2016
@ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type-security A security issue
Projects
None yet
Development

No branches or pull requests

1 participant