diff options
Diffstat (limited to 'Python/marshal.c')
| -rw-r--r-- | Python/marshal.c | 136 | 
1 files changed, 67 insertions, 69 deletions
diff --git a/Python/marshal.c b/Python/marshal.c index 1edb696..cc17329 100644 --- a/Python/marshal.c +++ b/Python/marshal.c @@ -31,6 +31,9 @@  #define TYPE_STOPITER           'S'  #define TYPE_ELLIPSIS           '.'  #define TYPE_INT                'i' +/* TYPE_INT64 is deprecated. It is not +   generated anymore, and support for reading it +   will be removed in Python 3.4. */  #define TYPE_INT64              'I'  #define TYPE_FLOAT              'f'  #define TYPE_BINARY_FLOAT       'g' @@ -59,9 +62,9 @@ typedef struct {      /* If fp == NULL, the following are valid: */      PyObject *readable;    /* Stream-like object being read from */      PyObject *str; +    PyObject *current_filename;      char *ptr;      char *end; -    PyObject *strings; /* dict on marshal, list on unmarshal */      int version;  } WFILE; @@ -92,7 +95,7 @@ w_more(int c, WFILE *p)  }  static void -w_string(char *s, Py_ssize_t n, WFILE *p) +w_string(const char *s, Py_ssize_t n, WFILE *p)  {      if (p->fp != NULL) {          fwrite(s, 1, n, p->fp); @@ -121,15 +124,6 @@ w_long(long x, WFILE *p)      w_byte((char)((x>>24) & 0xff), p);  } -#if SIZEOF_LONG > 4 -static void -w_long64(long x, WFILE *p) -{ -    w_long(x, p); -    w_long(x>>32, p); -} -#endif -  #define SIZE32_MAX  0x7FFFFFFF  #if SIZEOF_SIZE_T > 4 @@ -145,7 +139,14 @@ w_long64(long x, WFILE *p)  # define W_SIZE  w_long  #endif -/* We assume that Python longs are stored internally in base some power of +static void +w_pstring(const char *s, Py_ssize_t n, WFILE *p) +{ +        W_SIZE(n, p); +        w_string(s, n, p); +} + +/* We assume that Python ints are stored internally in base some power of     2**15; for the sake of portability we'll always read and write them in base     exactly 2**15. */ @@ -239,8 +240,8 @@ w_object(PyObject *v, WFILE *p)  #if SIZEOF_LONG > 4              long y = Py_ARITHMETIC_RIGHT_SHIFT(long, x, 31);              if (y && y != -1) { -                w_byte(TYPE_INT64, p); -                w_long64(x, p); +                /* Too large for TYPE_INT */ +                w_PyLong((PyLongObject*)v, p);              }              else  #endif @@ -319,24 +320,18 @@ w_object(PyObject *v, WFILE *p)      }      else if (PyBytes_CheckExact(v)) {          w_byte(TYPE_STRING, p); -        n = PyBytes_GET_SIZE(v); -        W_SIZE(n, p); -        w_string(PyBytes_AS_STRING(v), n, p); +        w_pstring(PyBytes_AS_STRING(v), PyBytes_GET_SIZE(v), p);      }      else if (PyUnicode_CheckExact(v)) {          PyObject *utf8; -        utf8 = PyUnicode_EncodeUTF8(PyUnicode_AS_UNICODE(v), -                                    PyUnicode_GET_SIZE(v), -                                    "surrogatepass"); +        utf8 = PyUnicode_AsEncodedString(v, "utf8", "surrogatepass");          if (utf8 == NULL) {              p->depth--;              p->error = WFERR_UNMARSHALLABLE;              return;          }          w_byte(TYPE_UNICODE, p); -        n = PyBytes_GET_SIZE(utf8); -        W_SIZE(n, p); -        w_string(PyBytes_AS_STRING(utf8), n, p); +        w_pstring(PyBytes_AS_STRING(utf8), PyBytes_GET_SIZE(utf8), p);          Py_DECREF(utf8);      }      else if (PyTuple_CheckExact(v)) { @@ -419,7 +414,6 @@ w_object(PyObject *v, WFILE *p)      }      else if (PyObject_CheckBuffer(v)) {          /* Write unknown buffer-style objects as a string */ -        char *s;          Py_buffer view;          if (PyObject_GetBuffer(v, &view, PyBUF_SIMPLE) != 0) {              w_byte(TYPE_UNKNOWN, p); @@ -428,10 +422,7 @@ w_object(PyObject *v, WFILE *p)              return;          }          w_byte(TYPE_STRING, p); -        n = view.len; -        s = view.buf; -        W_SIZE(n, p); -        w_string(s, n, p); +        w_pstring(view.buf, view.len, p);          PyBuffer_Release(&view);      }      else { @@ -441,7 +432,7 @@ w_object(PyObject *v, WFILE *p)      p->depth--;  } -/* version currently has no effect for writing longs. */ +/* version currently has no effect for writing ints. */  void  PyMarshal_WriteLongToFile(long x, FILE *fp, int version)  { @@ -449,7 +440,6 @@ PyMarshal_WriteLongToFile(long x, FILE *fp, int version)      wf.fp = fp;      wf.error = WFERR_OK;      wf.depth = 0; -    wf.strings = NULL;      wf.version = version;      w_long(x, &wf);  } @@ -461,10 +451,8 @@ PyMarshal_WriteObjectToFile(PyObject *x, FILE *fp, int version)      wf.fp = fp;      wf.error = WFERR_OK;      wf.depth = 0; -    wf.strings = (version > 0) ? PyDict_New() : NULL;      wf.version = version;      w_object(x, &wf); -    Py_XDECREF(wf.strings);  }  typedef WFILE RFILE; /* Same struct with different invariants */ @@ -489,7 +477,9 @@ r_string(char *s, Py_ssize_t n, RFILE *p)          }      }      else { -        PyObject *data = PyObject_CallMethod(p->readable, "read", "n", n); +        _Py_IDENTIFIER(read); + +        PyObject *data = _PyObject_CallMethodId(p->readable, &PyId_read, "n", n);          read = 0;          if (data != NULL) {              if (!PyBytes_Check(data)) { @@ -500,8 +490,17 @@ r_string(char *s, Py_ssize_t n, RFILE *p)              else {                  read = PyBytes_GET_SIZE(data);                  if (read > 0) { -                    ptr = PyBytes_AS_STRING(data); -                    memcpy(s, ptr, read); +                    if (read > n) { +                        PyErr_Format(PyExc_ValueError, +                                    "read() returned too much data: " +                                    "%zd bytes requested, %zd returned", +                                    n, read); +                        read = -1; +                    } +                    else { +                        ptr = PyBytes_AS_STRING(data); +                        memcpy(s, ptr, read); +                    }                  }              }              Py_DECREF(data); @@ -743,11 +742,13 @@ r_object(RFILE *p)              double dx;              retval = NULL;              n = r_byte(p); -            if (n == EOF || r_string(buf, n, p) != n) { +            if (n == EOF) {                  PyErr_SetString(PyExc_EOFError,                      "EOF read where object expected");                  break;              } +            if (r_string(buf, n, p) != n) +                break;              buf[n] = '\0';              dx = PyOS_string_to_double(buf, NULL, NULL);              if (dx == -1.0 && PyErr_Occurred()) @@ -761,8 +762,6 @@ r_object(RFILE *p)              unsigned char buf[8];              double x;              if (r_string((char*)buf, 8, p) != 8) { -                PyErr_SetString(PyExc_EOFError, -                    "EOF read where object expected");                  retval = NULL;                  break;              } @@ -781,21 +780,25 @@ r_object(RFILE *p)              Py_complex c;              retval = NULL;              n = r_byte(p); -            if (n == EOF || r_string(buf, n, p) != n) { +            if (n == EOF) {                  PyErr_SetString(PyExc_EOFError,                      "EOF read where object expected");                  break;              } +            if (r_string(buf, n, p) != n) +                break;              buf[n] = '\0';              c.real = PyOS_string_to_double(buf, NULL, NULL);              if (c.real == -1.0 && PyErr_Occurred())                  break;              n = r_byte(p); -            if (n == EOF || r_string(buf, n, p) != n) { +            if (n == EOF) {                  PyErr_SetString(PyExc_EOFError,                      "EOF read where object expected");                  break;              } +            if (r_string(buf, n, p) != n) +                break;              buf[n] = '\0';              c.imag = PyOS_string_to_double(buf, NULL, NULL);              if (c.imag == -1.0 && PyErr_Occurred()) @@ -809,8 +812,6 @@ r_object(RFILE *p)              unsigned char buf[8];              Py_complex c;              if (r_string((char*)buf, 8, p) != 8) { -                PyErr_SetString(PyExc_EOFError, -                    "EOF read where object expected");                  retval = NULL;                  break;              } @@ -820,8 +821,6 @@ r_object(RFILE *p)                  break;              }              if (r_string((char*)buf, 8, p) != 8) { -                PyErr_SetString(PyExc_EOFError, -                    "EOF read where object expected");                  retval = NULL;                  break;              } @@ -852,8 +851,6 @@ r_object(RFILE *p)          }          if (r_string(PyBytes_AS_STRING(v), n, p) != n) {              Py_DECREF(v); -            PyErr_SetString(PyExc_EOFError, -                            "EOF read where object expected");              retval = NULL;              break;          } @@ -881,8 +878,6 @@ r_object(RFILE *p)          }          if (r_string(buffer, n, p) != n) {              PyMem_DEL(buffer); -            PyErr_SetString(PyExc_EOFError, -                "EOF read where object expected");              retval = NULL;              break;          } @@ -1073,6 +1068,18 @@ r_object(RFILE *p)              filename = r_object(p);              if (filename == NULL)                  goto code_error; +            if (PyUnicode_CheckExact(filename)) { +                if (p->current_filename != NULL) { +                    if (!PyUnicode_Compare(filename, p->current_filename)) { +                        Py_DECREF(filename); +                        Py_INCREF(p->current_filename); +                        filename = p->current_filename; +                    } +                } +                else { +                    p->current_filename = filename; +                } +            }              name = r_object(p);              if (name == NULL)                  goto code_error; @@ -1135,7 +1142,7 @@ PyMarshal_ReadShortFromFile(FILE *fp)      assert(fp);      rf.readable = NULL;      rf.fp = fp; -    rf.strings = NULL; +    rf.current_filename = NULL;      rf.end = rf.ptr = NULL;      return r_short(&rf);  } @@ -1146,7 +1153,7 @@ PyMarshal_ReadLongFromFile(FILE *fp)      RFILE rf;      rf.fp = fp;      rf.readable = NULL; -    rf.strings = NULL; +    rf.current_filename = NULL;      rf.ptr = rf.end = NULL;      return r_long(&rf);  } @@ -1204,11 +1211,10 @@ PyMarshal_ReadObjectFromFile(FILE *fp)      PyObject *result;      rf.fp = fp;      rf.readable = NULL; -    rf.strings = PyList_New(0); +    rf.current_filename = NULL;      rf.depth = 0;      rf.ptr = rf.end = NULL;      result = r_object(&rf); -    Py_DECREF(rf.strings);      return result;  } @@ -1219,12 +1225,11 @@ PyMarshal_ReadObjectFromString(char *str, Py_ssize_t len)      PyObject *result;      rf.fp = NULL;      rf.readable = NULL; +    rf.current_filename = NULL;      rf.ptr = str;      rf.end = str + len; -    rf.strings = PyList_New(0);      rf.depth = 0;      result = r_object(&rf); -    Py_DECREF(rf.strings);      return result;  } @@ -1232,7 +1237,6 @@ PyObject *  PyMarshal_WriteObjectToString(PyObject *x, int version)  {      WFILE wf; -    PyObject *res = NULL;      wf.fp = NULL;      wf.readable = NULL; @@ -1244,9 +1248,7 @@ PyMarshal_WriteObjectToString(PyObject *x, int version)      wf.error = WFERR_OK;      wf.depth = 0;      wf.version = version; -    wf.strings = (version > 0) ? PyDict_New() : NULL;      w_object(x, &wf); -    Py_XDECREF(wf.strings);      if (wf.str != NULL) {          char *base = PyBytes_AS_STRING((PyBytesObject *)wf.str);          if (wf.ptr - base > PY_SSIZE_T_MAX) { @@ -1268,12 +1270,7 @@ PyMarshal_WriteObjectToString(PyObject *x, int version)                 :"object too deeply nested to marshal");          return NULL;      } -    if (wf.str != NULL) { -        /* XXX Quick hack -- need to do this differently */ -        res = PyBytes_FromObject(wf.str); -        Py_DECREF(wf.str); -    } -    return res; +    return wf.str;  }  /* And an interface for Python programs... */ @@ -1287,12 +1284,14 @@ marshal_dump(PyObject *self, PyObject *args)      int version = Py_MARSHAL_VERSION;      PyObject *s;      PyObject *res; +    _Py_IDENTIFIER(write); +      if (!PyArg_ParseTuple(args, "OO|i:dump", &x, &f, &version))          return NULL;      s = PyMarshal_WriteObjectToString(x, version);      if (s == NULL)          return NULL; -    res = PyObject_CallMethod(f, "write", "O", s); +    res = _PyObject_CallMethodId(f, &PyId_write, "O", s);      Py_DECREF(s);      return res;  } @@ -1314,6 +1313,7 @@ static PyObject *  marshal_load(PyObject *self, PyObject *f)  {      PyObject *data, *result; +    _Py_IDENTIFIER(read);      RFILE rf;      /* @@ -1321,7 +1321,7 @@ marshal_load(PyObject *self, PyObject *f)       * This is to ensure that the object passed in at least       * has a read method which returns bytes.       */ -    data = PyObject_CallMethod(f, "read", "i", 0); +    data = _PyObject_CallMethodId(f, &PyId_read, "i", 0);      if (data == NULL)          return NULL;      if (!PyBytes_Check(data)) { @@ -1331,12 +1331,11 @@ marshal_load(PyObject *self, PyObject *f)          result = NULL;      }      else { -        rf.strings = PyList_New(0);          rf.depth = 0;          rf.fp = NULL;          rf.readable = f; +        rf.current_filename = NULL;          result = read_object(&rf); -        Py_DECREF(rf.strings);      }      Py_DECREF(data);      return result; @@ -1389,12 +1388,11 @@ marshal_loads(PyObject *self, PyObject *args)      n = p.len;      rf.fp = NULL;      rf.readable = NULL; +    rf.current_filename = NULL;      rf.ptr = s;      rf.end = s + n; -    rf.strings = PyList_New(0);      rf.depth = 0;      result = read_object(&rf); -    Py_DECREF(rf.strings);      PyBuffer_Release(&p);      return result;  }  | 
