File tree Expand file tree Collapse file tree 3 files changed +73
-6
lines changed
Expand file tree Collapse file tree 3 files changed +73
-6
lines changed Original file line number Diff line number Diff line change @@ -45,7 +45,7 @@ typedef struct {
4545} _PyManagedBufferObject ;
4646
4747
48- /* static storage used for casting between formats */
48+ /* deprecated, removed in 3.5 */
4949#define _Py_MEMORYVIEW_MAX_FORMAT 3 /* must be >= 3 */
5050
5151/* memoryview state flags */
@@ -62,7 +62,7 @@ typedef struct {
6262 int flags ; /* state flags */
6363 Py_ssize_t exports ; /* number of buffer re-exports */
6464 Py_buffer view ; /* private copy of the exporter's view */
65- char format [_Py_MEMORYVIEW_MAX_FORMAT ]; /* used for casting */
65+ char format [_Py_MEMORYVIEW_MAX_FORMAT ]; /* deprecated, removed in 3.5 */
6666 PyObject * weakreflist ;
6767 Py_ssize_t ob_array [1 ]; /* shape, strides, suboffsets */
6868} PyMemoryViewObject ;
Original file line number Diff line number Diff line change @@ -360,6 +360,25 @@ def test_reversed(self):
360360 self .assertEqual (list (reversed (m )), aslist )
361361 self .assertEqual (list (reversed (m )), list (m [::- 1 ]))
362362
363+ def test_issue22668 (self ):
364+ m = memoryview (bytes (range (8 )))
365+ b = m .cast ('H' )
366+ c = b [0 :2 ]
367+ d = memoryview (b )
368+
369+ del b
370+
371+ self .assertEqual (c [0 ], 256 )
372+ self .assertEqual (d [0 ], 256 )
373+ self .assertEqual (c .format , "H" )
374+ self .assertEqual (d .format , "H" )
375+
376+ _ = m .cast ('I' )
377+ self .assertEqual (c [0 ], 256 )
378+ self .assertEqual (d [0 ], 256 )
379+ self .assertEqual (c .format , "H" )
380+ self .assertEqual (d .format , "H" )
381+
363382
364383# Variations on source objects for the buffer: bytes-like objects, then arrays
365384# with itemsize > 1.
Original file line number Diff line number Diff line change @@ -1135,6 +1135,51 @@ get_native_fmtchar(char *result, const char *fmt)
11351135 return -1 ;
11361136}
11371137
1138+ Py_LOCAL_INLINE (char * )
1139+ get_native_fmtstr (const char * fmt )
1140+ {
1141+ int at = 0 ;
1142+
1143+ if (fmt [0 ] == '@' ) {
1144+ at = 1 ;
1145+ fmt ++ ;
1146+ }
1147+ if (fmt [0 ] == '\0' || fmt [1 ] != '\0' ) {
1148+ return NULL ;
1149+ }
1150+
1151+ #define RETURN (s ) do { return at ? "@" s : s; } while (0)
1152+
1153+ switch (fmt [0 ]) {
1154+ case 'c' : RETURN ("c" );
1155+ case 'b' : RETURN ("b" );
1156+ case 'B' : RETURN ("B" );
1157+ case 'h' : RETURN ("h" );
1158+ case 'H' : RETURN ("H" );
1159+ case 'i' : RETURN ("i" );
1160+ case 'I' : RETURN ("I" );
1161+ case 'l' : RETURN ("l" );
1162+ case 'L' : RETURN ("L" );
1163+ #ifdef HAVE_LONG_LONG
1164+ case 'q' : RETURN ("q" );
1165+ case 'Q' : RETURN ("Q" );
1166+ #endif
1167+ case 'n' : RETURN ("n" );
1168+ case 'N' : RETURN ("N" );
1169+ case 'f' : RETURN ("f" );
1170+ case 'd' : RETURN ("d" );
1171+ #ifdef HAVE_C99_BOOL
1172+ case '?' : RETURN ("?" );
1173+ #else
1174+ case '?' : RETURN ("?" );
1175+ #endif
1176+ case 'P' : RETURN ("P" );
1177+ }
1178+
1179+ return NULL ;
1180+ }
1181+
1182+
11381183/* Cast a memoryview's data type to 'format'. The input array must be
11391184 C-contiguous. At least one of input-format, output-format must have
11401185 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)
11841229 goto out ;
11851230 }
11861231
1187- strncpy (mv -> format , PyBytes_AS_STRING (asciifmt ),
1188- _Py_MEMORYVIEW_MAX_FORMAT );
1189- mv -> format [_Py_MEMORYVIEW_MAX_FORMAT - 1 ] = '\0' ;
1190- view -> format = mv -> format ;
1232+ view -> format = get_native_fmtstr (PyBytes_AS_STRING (asciifmt ));
1233+ if (view -> format == NULL ) {
1234+ /* NOT_REACHED: get_native_fmtchar() already validates the format. */
1235+ PyErr_SetString (PyExc_RuntimeError ,
1236+ "memoryview: internal error" );
1237+ goto out ;
1238+ }
11911239 view -> itemsize = itemsize ;
11921240
11931241 view -> ndim = 1 ;
You can’t perform that action at this time.
0 commit comments