Why does a switch break cause a segmentation fault

Boris Carvajal boris2.9 at gmail.com
Tue Jul 23 15:28:37 UTC 2019


On Tuesday, 23 July 2019 at 08:04:07 UTC, adamgoldberg wrote:
> On Tuesday, 23 July 2019 at 00:01:09 UTC, Exil wrote:
>> On Monday, 22 July 2019 at 22:05:17 UTC, adamgoldberg wrote:
>>> Hey, I just happened to be writing a program in D an stumbled 
>>> upon a bug, that causes it to terminate after receiving a 
>>> SEGV signal, nothing wierd so far but it looks everything I 
>>> tried shows it is the break statement inside of a switch.
>>> It seems to have a relatively random chance of occuring, and 
>>> also somewhat dependant on the compiler, and build mode used.
>>> I'm short on time so instead of rewriting my SO post I will 
>>> just link it.
>>>
>>> Here! 
>>> https://stackoverflow.com/questions/57153617/random-segmentation-fault-in-d-lang-on-switch-break
>>>
>>> Hope someone can help!
>>
>> Could be the statement in the actual switch(), which is 
>> accessing a pointer "codecpar".
>>
>>     switch (stream.codecpar.codec_type)
>>                     ^^^^^
>>
>> This could be null and you aren't checking for it. I find that 
>> D sometimes doesn't have the correct line numbers for debug 
>> info, even when not doing an optimized build. So it could 
>> really be anything in that function.
>>
>> The root cause could be a lot of things though, some bad 
>> codegen or otherwise. Could add a check to make sure though.
>
> I ran the program after adding
>
>    enforce (stream.codecpar != null);
>
> and nothing changed, and by nothing I mean that DMD in debug 
> mode still doesnt crash but DMD in release does (like 70% of 
> the time), I think its more important to address that issue 
> because I can't seem to find any explenation of this behaviour, 
> yet it occurs.

The struct AVStream is different on the D side (avformat.d) than 
the original C header, at least on my PC using ffmpeg 4.1.4.

So instead of getting codecpar member we get some unrelated data 
and dereferencing it can crash the program.

I tried using the DPP project, it errors out but the generated 
file is almost there, just commenting 1 line and changing some 
not found type pointer member to void pointer I got a working 
example with your same code.

Here is the updated struct part, the program will run fine with 
this layout.

struct AVStream
     {
         int index;
         int id;
         AVCodecContext* codec;
         void* priv_data;
         AVRational time_base;
         c_long start_time;
         c_long duration;
         c_long nb_frames;
         int disposition;
         AVDiscard discard;
         AVRational sample_aspect_ratio;
         AVDictionary* metadata;
         AVRational avg_frame_rate;
         AVPacket attached_pic;
         AVPacketSideData* side_data;
         int nb_side_data;
         int event_flags;
         AVRational r_frame_rate;
         char* recommended_encoder_configuration;
         AVCodecParameters* codecpar;
         static struct _Anonymous_9
         {
             c_long last_dts;
             c_long duration_gcd;
             int duration_count;
             c_long rfps_duration_sum;
             double[399]** duration_error;
             c_long codec_info_duration;
             c_long codec_info_duration_fields;
             int frame_delay_evidence;
             int found_decoder;
             c_long last_duration;
             c_long fps_first_dts;
             int fps_first_dts_idx;
             c_long fps_last_dts;
             int fps_last_dts_idx;
         }
         _Anonymous_9 _anonymous_10;
         auto last_dts() @property @nogc pure nothrow { return 
_anonymous_10.last_dts; }
         void last_dts(_T_)(auto ref _T_ val) @property @nogc pure 
nothrow { _anonymous_10.last_dts = val; }
         auto duration_gcd() @property @nogc pure nothrow { return 
_anonymous_10.duration_gcd; }
         void duration_gcd(_T_)(auto ref _T_ val) @property @nogc 
pure nothrow { _anonymous_10.duration_gcd = val; }
         auto duration_count() @property @nogc pure nothrow { 
return _anonymous_10.duration_count; }
         void duration_count(_T_)(auto ref _T_ val) @property 
@nogc pure nothrow { _anonymous_10.duration_count = val; }
         auto rfps_duration_sum() @property @nogc pure nothrow { 
return _anonymous_10.rfps_duration_sum; }
         void rfps_duration_sum(_T_)(auto ref _T_ val) @property 
@nogc pure nothrow { _anonymous_10.rfps_duration_sum = val; }
         auto duration_error() @property @nogc pure nothrow { 
return _anonymous_10.duration_error; }
         void duration_error(_T_)(auto ref _T_ val) @property 
@nogc pure nothrow { _anonymous_10.duration_error = val; }
         auto codec_info_duration() @property @nogc pure nothrow { 
return _anonymous_10.codec_info_duration; }
         void codec_info_duration(_T_)(auto ref _T_ val) @property 
@nogc pure nothrow { _anonymous_10.codec_info_duration = val; }
         auto codec_info_duration_fields() @property @nogc pure 
nothrow { return _anonymous_10.codec_info_duration_fields; }
         void codec_info_duration_fields(_T_)(auto ref _T_ val) 
@property @nogc pure nothrow { 
_anonymous_10.codec_info_duration_fields = val; }
         auto frame_delay_evidence() @property @nogc pure nothrow 
{ return _anonymous_10.frame_delay_evidence; }
         void frame_delay_evidence(_T_)(auto ref _T_ val) 
@property @nogc pure nothrow { _anonymous_10.frame_delay_evidence 
= val; }
         auto found_decoder() @property @nogc pure nothrow { 
return _anonymous_10.found_decoder; }
         void found_decoder(_T_)(auto ref _T_ val) @property @nogc 
pure nothrow { _anonymous_10.found_decoder = val; }
         auto last_duration() @property @nogc pure nothrow { 
return _anonymous_10.last_duration; }
         void last_duration(_T_)(auto ref _T_ val) @property @nogc 
pure nothrow { _anonymous_10.last_duration = val; }
         auto fps_first_dts() @property @nogc pure nothrow { 
return _anonymous_10.fps_first_dts; }
         void fps_first_dts(_T_)(auto ref _T_ val) @property @nogc 
pure nothrow { _anonymous_10.fps_first_dts = val; }
         auto fps_first_dts_idx() @property @nogc pure nothrow { 
return _anonymous_10.fps_first_dts_idx; }
         void fps_first_dts_idx(_T_)(auto ref _T_ val) @property 
@nogc pure nothrow { _anonymous_10.fps_first_dts_idx = val; }
         auto fps_last_dts() @property @nogc pure nothrow { return 
_anonymous_10.fps_last_dts; }
         void fps_last_dts(_T_)(auto ref _T_ val) @property @nogc 
pure nothrow { _anonymous_10.fps_last_dts = val; }
         auto fps_last_dts_idx() @property @nogc pure nothrow { 
return _anonymous_10.fps_last_dts_idx; }
         void fps_last_dts_idx(_T_)(auto ref _T_ val) @property 
@nogc pure nothrow { _anonymous_10.fps_last_dts_idx = val; }
         _Anonymous_9* info;
         int pts_wrap_bits;
         c_long first_dts;
         c_long cur_dts;
         c_long last_IP_pts;
         int last_IP_duration;
         int probe_packets;
         int codec_info_nb_frames;
         AVStreamParseType need_parsing;
         AVCodecParserContext* parser;
         AVPacketList* last_in_packet_buffer;
         AVProbeData probe_data;
         c_long[17] pts_buffer;
         AVIndexEntry* index_entries;
         int nb_index_entries;
         uint index_entries_allocated_size;
         int stream_identifier;
         int program_num;
         int pmt_version;
         int pmt_stream_idx;
         c_long interleaver_chunk_size;
         c_long interleaver_chunk_duration;
         int request_probe;
         int skip_to_keyframe;
         int skip_samples;
         c_long start_skip_samples;
         c_long first_discard_sample;
         c_long last_discard_sample;
         int nb_decoded_frames;
         c_long mux_ts_offset;
         c_long pts_wrap_reference;
         int pts_wrap_behavior;
         int update_initial_durations_done;
         c_long[17] pts_reorder_error;
         ubyte[17] pts_reorder_error_count;
         c_long last_dts_for_order_check;
         ubyte dts_ordered;
         ubyte dts_misordered;
         int inject_global_side_data;
         AVRational display_aspect_ratio;
         AVStreamInternal* internal;
     }





More information about the Digitalmars-d-learn mailing list