summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Include/memoryobject.h4
-rw-r--r--Lib/test/test_memoryview.py19
-rw-r--r--Objects/memoryobject.c56
3 files changed, 73 insertions, 6 deletions
diff --git a/Include/memoryobject.h b/Include/memoryobject.h
index c2e1194..382ca92 100644
--- a/Include/memoryobject.h
+++ b/Include/memoryobject.h
@@ -45,7 +45,7 @@ typedef struct {
} _PyManagedBufferObject;
-/* static storage used for casting between formats */
+/* deprecated, removed in 3.5 */
#define _Py_MEMORYVIEW_MAX_FORMAT 3 /* must be >= 3 */
/* memoryview state flags */
@@ -62,7 +62,7 @@ typedef struct {
int flags; /* state flags */
Py_ssize_t exports; /* number of buffer re-exports */
Py_buffer view; /* private copy of the exporter's view */
- char format[_Py_MEMORYVIEW_MAX_FORMAT]; /* used for casting */
+ char format[_Py_MEMORYVIEW_MAX_FORMAT]; /* deprecated, removed in 3.5 */
PyObject *weakreflist;
Py_ssize_t ob_array[1]; /* shape, strides, suboffsets */
} PyMemoryViewObject;
diff --git a/Lib/test/test_memoryview.py b/Lib/test/test_memoryview.py
index e7df8a7..bd9d0d4 100644
--- a/Lib/test/test_memoryview.py
+++ b/Lib/test/test_memoryview.py
@@ -360,6 +360,25 @@ class AbstractMemoryTests:
self.assertEqual(list(reversed(m)), aslist)
self.assertEqual(list(reversed(m)), list(m[::-1]))
+ def test_issue22668(self):
+ m = memoryview(bytes(range(8)))
+ b = m.cast('H')
+ c = b[0:2]
+ d = memoryview(b)
+
+ del b
+
+ self.assertEqual(c[0], 256)
+ self.assertEqual(d[0], 256)
+ self.assertEqual(c.format, "H")
+ self.assertEqual(d.format, "H")
+
+ _ = m.cast('I')
+ self.assertEqual(c[0], 256)
+ self.assertEqual(d[0], 256)
+ self.assertEqual(c.format, "H")
+ self.assertEqual(d.format, "H")
+
# Variations on source objects for the buffer: bytes-like objects, then arrays
# with itemsize > 1.
diff --git a/Objects/memoryobject.c b/Objects/memoryobject.c
index cb644b8..0be8493 100644
--- a/Objects/memoryobject.c
+++ b/Objects/memoryobject.c
@@ -1135,6 +1135,51 @@ get_native_fmtchar(char *result, const char *fmt)
return -1;
}
+Py_LOCAL_INLINE(char *)
+get_native_fmtstr(const char *fmt)
+{
+ int at = 0;
+
+ if (fmt[0] == '@') {
+ at = 1;
+ fmt++;
+ }
+ if (fmt[0] == '\0' || fmt[1] != '\0') {
+ return NULL;
+ }
+
+#define RETURN(s) do { return at ? "@" s : s; } while (0)
+
+ switch (fmt[0]) {
+ case 'c': RETURN("c");
+ case 'b': RETURN("b");
+ case 'B': RETURN("B");
+ case 'h': RETURN("h");
+ case 'H': RETURN("H");
+ case 'i': RETURN("i");
+ case 'I': RETURN("I");
+ case 'l': RETURN("l");
+ case 'L': RETURN("L");
+ #ifdef HAVE_LONG_LONG
+ case 'q': RETURN("q");
+ case 'Q': RETURN("Q");
+ #endif
+ case 'n': RETURN("n");
+ case 'N': RETURN("N");
+ case 'f': RETURN("f");
+ case 'd': RETURN("d");
+ #ifdef HAVE_C99_BOOL
+ case '?': RETURN("?");
+ #else
+ case '?': RETURN("?");
+ #endif
+ case 'P': RETURN("P");
+ }
+
+ return NULL;
+}
+
+
/* Cast a memoryview's data type to 'format'. The input array must be
C-contiguous. At least one of input-format, output-format must have
byte size. The output array is 1-D, with the same byte length as the
@@ -1184,10 +1229,13 @@ cast_to_1D(PyMemoryViewObject *mv, PyObject *format)
goto out;
}
- strncpy(mv->format, PyBytes_AS_STRING(asciifmt),
- _Py_MEMORYVIEW_MAX_FORMAT);
- mv->format[_Py_MEMORYVIEW_MAX_FORMAT-1] = '\0';
- view->format = mv->format;
+ view->format = get_native_fmtstr(PyBytes_AS_STRING(asciifmt));
+ if (view->format == NULL) {
+ /* NOT_REACHED: get_native_fmtchar() already validates the format. */
+ PyErr_SetString(PyExc_RuntimeError,
+ "memoryview: internal error");
+ goto out;
+ }
view->itemsize = itemsize;
view->ndim = 1;