Comment 10 for bug 990947

Revision history for this message
Dimo (lami4ka) wrote :

I also ran into this, and dug a little in the core file. This is the stack trace we see:

#0 0x00007f01ec5dc83b in dca_syncinfo () from /usr/lib/libdca.so.0
#1 0x00007f01ec80ab7b in gst_dtsdec_parse (bdec=0x7f01e804e320,
    adapter=<optimized out>, _offset=0x7f01ed20d9fc, len=0x7f01ed20d9f8)
    at gstdtsdec.c:297
#2 0x00007f01effdc0ec in gst_audio_decoder_push_buffers (dec=0x7f01e804e320,
    force=0) at gstaudiodecoder.c:988
#3 0x00007f01effdc5a0 in gst_audio_decoder_chain_forward (dec=0x7f01e804e320,
    buffer=0x0) at gstaudiodecoder.c:1141
#4 0x00007f01effdd35b in gst_audio_decoder_chain (pad=<optimized out>,
    buffer=0x1e869f0) at gstaudiodecoder.c:1389
#5 0x00007f01ec809c97 in gst_dtsdec_chain (pad=0x7f01e803c1c0, buf=0x1e7cee0)
    at gstdtsdec.c:715
#6 0x00007f01f673222a in gst_pad_chain_data_unchecked (cache=0x7f01ed20dc20,
    data=0x1e7cee0, is_buffer=1, pad=0x7f01e803c1c0) at gstpad.c:4271
#7 gst_pad_push_data (pad=<optimized out>, is_buffer=1, data=0x1e7cee0,
    cache=<optimized out>) at gstpad.c:4506
#8 0x00007f01f6735ae6 in gst_pad_push (pad=0x7f01e803c040, buffer=0x1e7cee0)
    at gstpad.c:4730
#9 0x00007f01f31f6536 in gst_single_queue_push_one (object=0x1e7cee0,
    sq=0x7f01e803eaf0, mq=0x7f01e803f050) at gstmultiqueue.c:1087
#10 gst_multi_queue_loop (pad=<optimized out>) at gstmultiqueue.c:1318
#11 0x00007f01f675bdcc in gst_task_func (task=0x1ed5610) at gsttask.c:327
#12 0x00007f01f5ff2248 in ?? () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#13 0x00007f01f5ff19e5 in ?? () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#14 0x00007f01f5d6fe9a in start_thread ()
   from /lib/x86_64-linux-gnu/libpthread.so.0
#15 0x00007f01f5a9a4bd in clone () from /lib/x86_64-linux-gnu/libc.so.6
#16 0x0000000000000000 in ?? ()

The faulting instruction is:

   0x00007f01ec5dc820 <+0>: mov %rbx,-0x20(%rsp)
   0x00007f01ec5dc825 <+5>: mov %rbp,-0x18(%rsp)
   0x00007f01ec5dc82a <+10>: mov %rdi,%rbx
   0x00007f01ec5dc82d <+13>: mov %r12,-0x10(%rsp)
   0x00007f01ec5dc832 <+18>: mov %r13,-0x8(%rsp)
   0x00007f01ec5dc837 <+23>: sub $0x38,%rsp
   0x00007f01ec5dc83b <+27>: movzbl (%rsi),%eax <<<---- This one

Where $rsi is not mapped. dca_syncinfo gets $rsi from gst_dtsdec_parse(). Looking at gst_dtsdec_parse(), $rsi comes from $r12, which when we map it (manually :() to the source code, corresponds to the variable data in gst_dtsdec_parse():

static GstFlowReturn
gst_dtsdec_parse (GstAudioDecoder * bdec, GstAdapter * adapter,
    gint * _offset, gint * len)
{
...
  guint8 *data;
...
  size = av = gst_adapter_available (adapter);
  data = (guint8 *) gst_adapter_peek (adapter, av);
...
  while (av >= 7) {
    length = dca_syncinfo (dts->state, data, &flags,
        &sample_rate, &bit_rate, &frame_length);

    if (length == 0) {
      /* shift window to re-find sync */
      data++;
      size--;
    } else if (length <= size) {
      GST_LOG_OBJECT (dts, "Sync: frame size %d", length);
      result = GST_FLOW_OK;
      break;
    } else {
      GST_LOG_OBJECT (dts, "Not enough data available (needed %d had %d)",
          length, size);
      break;
    }
  }
....

Note that the loop condition does not depend on either size nor data. We only exit the loop if length is non-0. length comes from dca_syncinfo(), which looks for a certain bit pattern at the start of *data, and if it doesn't find it, it returns 0.

So if we are given bad data, that doesn't have the given bit segment dca_syncinfo() looks for, length will always be 0, we will keep looping, incrementing data and decrementing size until we fall outside of the buffer, which I think is whats happening.

This by the way is fixed upstream in gstreamer by the following commit:

http://cgit.freedesktop.org/gstreamer/gst-plugins-bad/commit/ext/dts/gstdtsdec.c?id=860ccd414dbb313fabf065b92838f0f39037584b