@@ -1416,6 +1416,26 @@ def test_setitems_on_non_dicts(self):
1416
1416
1417
1417
FRAME_SIZE_TARGET = 64 * 1024
1418
1418
1419
+ def check_frame_opcodes (self , pickled ):
1420
+ """
1421
+ Check the arguments of FRAME opcodes in a protocol 4+ pickle.
1422
+ """
1423
+ frame_opcode_size = 9
1424
+ last_arg = last_pos = None
1425
+ for op , arg , pos in pickletools .genops (pickled ):
1426
+ if op .name != 'FRAME' :
1427
+ continue
1428
+ if last_pos is not None :
1429
+ # The previous frame's size should be equal to the number
1430
+ # of bytes up to the current frame.
1431
+ frame_size = pos - last_pos - frame_opcode_size
1432
+ self .assertEqual (frame_size , last_arg )
1433
+ last_arg , last_pos = arg , pos
1434
+ # The last frame's size should be equal to the number of bytes up
1435
+ # to the pickle's end.
1436
+ frame_size = len (pickled ) - last_pos - frame_opcode_size
1437
+ self .assertEqual (frame_size , last_arg )
1438
+
1419
1439
def test_framing_many_objects (self ):
1420
1440
obj = list (range (10 ** 5 ))
1421
1441
for proto in range (4 , pickle .HIGHEST_PROTOCOL + 1 ):
@@ -1429,6 +1449,7 @@ def test_framing_many_objects(self):
1429
1449
self .FRAME_SIZE_TARGET / 2 )
1430
1450
self .assertLessEqual (bytes_per_frame ,
1431
1451
self .FRAME_SIZE_TARGET * 1 )
1452
+ self .check_frame_opcodes (pickled )
1432
1453
1433
1454
def test_framing_large_objects (self ):
1434
1455
N = 1024 * 1024
@@ -1440,6 +1461,7 @@ def test_framing_large_objects(self):
1440
1461
self .assertEqual (obj , unpickled )
1441
1462
n_frames = count_opcode (pickle .FRAME , pickled )
1442
1463
self .assertGreaterEqual (n_frames , len (obj ))
1464
+ self .check_frame_opcodes (pickled )
1443
1465
1444
1466
def test_optional_frames (self ):
1445
1467
if pickle .HIGHEST_PROTOCOL < 4 :
0 commit comments