@@ -844,6 +844,42 @@ def test_invalid_path_error_preserves_pathlib(self):
844844 _remote_debugging .BinaryReader (missing )
845845 self .assertEqual (os .fspath (cm .exception .filename ), os .fspath (missing ))
846846
847+ def test_writer_rejects_malformed_samples (self ):
848+ """Malformed sample containers raise TypeError instead of crashing."""
849+ cases = (
850+ ("stack_frames" , 42 ),
851+ ("interp_info" , [42 ]),
852+ ("interp_info" , [()]),
853+ ("interp_info" , [(0 ,)]),
854+ ("threads" , [(0 , 42 )]),
855+ ("thread_info" , [(0 , [42 ])]),
856+ ("thread_info" , [(0 , [()])]),
857+ ("thread_info" , [(0 , [(1 ,)])]),
858+ ("thread_info" , [(0 , [(1 , 0 )])]),
859+ ("frame_list" , [(0 , [(1 , 0 , 42 )])]),
860+ ("frame_info" , [(0 , [(1 , 0 , [42 ])])]),
861+ ("frame_info" , [(0 , [(1 , 0 , [()])])]),
862+ ("frame_info" , [(0 , [(1 , 0 , [("a.py" ,)])])]),
863+ ("frame_info" , [(0 , [(1 , 0 , [("a.py" , None )])])]),
864+ ("frame_info" , [(0 , [(1 , 0 , [("a.py" , None , "f" )])])]),
865+ ("location" , [(0 , [(1 , 0 , [("a.py" , 42 , "f" , None )])])]),
866+ ("location" , [(0 , [(1 , 0 , [("a.py" , (), "f" , None )])])]),
867+ ("location" , [(0 , [(1 , 0 , [("a.py" , (1 ,), "f" , None )])])]),
868+ ("location" , [(0 , [(1 , 0 , [("a.py" , (1 , 1 ), "f" , None )])])]),
869+ ("location" , [(0 , [(1 , 0 , [("a.py" , (1 , 1 , 0 ), "f" , None )])])]),
870+ )
871+ with tempfile .NamedTemporaryFile (suffix = ".bin" , delete = False ) as f :
872+ filename = f .name
873+ self .temp_files .append (filename )
874+
875+ for field , sample in cases :
876+ with self .subTest (field = field , sample = sample ):
877+ with _remote_debugging .BinaryWriter (
878+ filename , 1000 , 0 , compression = 0
879+ ) as writer :
880+ with self .assertRaisesRegex (TypeError , field ):
881+ writer .write_sample (sample , 2000 )
882+
847883 def test_writer_handles_empty_stack_first_sample (self ):
848884 """BinaryWriter.write_sample tolerates an empty stack on a fresh thread.
849885
0 commit comments