Thread overview
Why does a switch break cause a segmentation fault
Jul 22, 2019
adamgoldberg
Jul 22, 2019
eric
Jul 23, 2019
Exil
Jul 23, 2019
adamgoldberg
Jul 23, 2019
Boris Carvajal
July 22, 2019
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!
July 22, 2019
Shouldn't (stream == null) be (stream is null)?

-Eric


From: "adamgoldberg via Digitalmars-d-learn" <digitalmars-d-learn@puremagic.com> To: digitalmars-d-learn@puremagic.com Sent: Monday, July 22, 2019 3:05:17 PM Subject: Why does a switch break cause a segmentation fault

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!


July 23, 2019
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.




July 23, 2019
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.


July 23, 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;
    }