zapping-vbi / zvbi

Vertical Blanking Interval (VBI) utilities
Other
5 stars 4 forks source link

segfault on a particular (bad?) byte sequence #2

Open ileanadumitrescu95 opened 2 years ago

ileanadumitrescu95 commented 2 years ago

SourceForge bug #189 written by Brian Enigma on 2011-08-31

I have a video file I've captured from over the air and am using libzvbi to parse out captions. I'm not sure if the capture has garbage (or how much garbage it may have), but it's causing zvbi to segfault. I've extracted out the VBI bytes near that bad point in the file into an array and wrapped it in a little driver program that should easily demonstrate the segfault (see attached).

bytesequencetest.cpp.txt

Comments by Brian Enigma:

Program received signal SIGSEGV, Segmentation fault. 0x0000003f21e7c312 in memcpy () from /lib64/libc.so.6 (gdb) bt

#0 0x0000003f21e7c312 in memcpy () from /lib64/libc.so.6
#1 0x00002aaaaaacc092 in update (cc=<value optimized out>, ch=0x2aaaaad56158,
upd=1) at caption.c:783
#\2 word_break (cc=<value optimized out>, ch=0x2aaaaad56158, upd=1)
at caption.c:825
#3 0x00002aaaaaacdcea in vbi_decode_caption (vbi=0x2aaaaad48010,
line=<value optimized out>, buf=0x7fffffffd228 "\034 ") at caption.c:859
#4 0x00002aaaaaafc883 in vbi_decode (vbi=0x2aaaaad48010,
sliced=0x7fffffffd220, lines=1, time=9.5999999999999872) at vbi.c:463
#5 0x0000000000400b8e in ProcessData() ()
#6 0x0000000000400bd2 in main ()

(gdb)

Replacing caption.c's update() function with one that employs bounds-checking protects against the segfault, but I don't yet understand how the state machine sets the ch->line pointer to such a weird value. This is within the vbi.channel[1] struct.

static inline void
update(cc_channel *ch)
{
// Bounds-check ch->line
if ( (ch->line >= &ch->pg[0].text[0] && ch->line < &ch->pg[0].text[1056 - COLUMNS])
|| (ch->line >= &ch->pg[1].text[0] && ch->line < &ch->pg[1].text[1056 - COLUMNS])
)
{
vbi_char *acp = ch->line - ch->pg[0].text + ch->pg[1].text;
// Bounds-check acp
if ( (acp >= &ch->pg[0].text[0] && acp < &ch->pg[0].text[1056 - COLUMNS])
|| (acp >= &ch->pg[1].text[0] && acp < &ch->pg[1].text[1056 - COLUMNS])
)
{
memcpy(acp, ch->line, sizeof(*acp) * COLUMNS);
}
}
}