mirror of https://github.com/python/cpython
Issue #22668: Ensure that format strings survive slicing after casting.
This commit is contained in:
parent
2934262fd3
commit
fa5d6a5ff3
|
@ -45,7 +45,7 @@ typedef struct {
|
||||||
} _PyManagedBufferObject;
|
} _PyManagedBufferObject;
|
||||||
|
|
||||||
|
|
||||||
/* static storage used for casting between formats */
|
/* deprecated, removed in 3.5 */
|
||||||
#define _Py_MEMORYVIEW_MAX_FORMAT 3 /* must be >= 3 */
|
#define _Py_MEMORYVIEW_MAX_FORMAT 3 /* must be >= 3 */
|
||||||
|
|
||||||
/* memoryview state flags */
|
/* memoryview state flags */
|
||||||
|
@ -62,7 +62,7 @@ typedef struct {
|
||||||
int flags; /* state flags */
|
int flags; /* state flags */
|
||||||
Py_ssize_t exports; /* number of buffer re-exports */
|
Py_ssize_t exports; /* number of buffer re-exports */
|
||||||
Py_buffer view; /* private copy of the exporter's view */
|
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;
|
PyObject *weakreflist;
|
||||||
Py_ssize_t ob_array[1]; /* shape, strides, suboffsets */
|
Py_ssize_t ob_array[1]; /* shape, strides, suboffsets */
|
||||||
} PyMemoryViewObject;
|
} PyMemoryViewObject;
|
||||||
|
|
|
@ -360,6 +360,25 @@ class AbstractMemoryTests:
|
||||||
self.assertEqual(list(reversed(m)), aslist)
|
self.assertEqual(list(reversed(m)), aslist)
|
||||||
self.assertEqual(list(reversed(m)), list(m[::-1]))
|
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
|
# Variations on source objects for the buffer: bytes-like objects, then arrays
|
||||||
# with itemsize > 1.
|
# with itemsize > 1.
|
||||||
|
|
|
@ -1135,6 +1135,51 @@ get_native_fmtchar(char *result, const char *fmt)
|
||||||
return -1;
|
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
|
/* 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
|
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
|
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;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
strncpy(mv->format, PyBytes_AS_STRING(asciifmt),
|
view->format = get_native_fmtstr(PyBytes_AS_STRING(asciifmt));
|
||||||
_Py_MEMORYVIEW_MAX_FORMAT);
|
if (view->format == NULL) {
|
||||||
mv->format[_Py_MEMORYVIEW_MAX_FORMAT-1] = '\0';
|
/* NOT_REACHED: get_native_fmtchar() already validates the format. */
|
||||||
view->format = mv->format;
|
PyErr_SetString(PyExc_RuntimeError,
|
||||||
|
"memoryview: internal error");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
view->itemsize = itemsize;
|
view->itemsize = itemsize;
|
||||||
|
|
||||||
view->ndim = 1;
|
view->ndim = 1;
|
||||||
|
|
Loading…
Reference in New Issue