Hello,
I've compiled vdr on alpinelinux 2.5.0 and get a segfault during start of vdr. Even without plugins I get this segfault (I didn't apply any patch to vdr sources). Vdr was started with the command:
/usr/local/bin/vdr --config=/etc/vdr --epgfile=/tmp/epg.data --grab=/dev/shm --log=3.1 --mute --no-kbd --user=root --video=/remote/vdr/
I've made a backtrace with gdb:
--snip-- vdrservernew:/tmp# gdb --core core /usr/local/bin/vdr GNU gdb (GDB) 7.5 Copyright (C) 2012 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later http://gnu.org/licenses/gpl.html This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-unknown-linux-gnu". For bug reporting instructions, please see: http://www.gnu.org/software/gdb/bugs/... Reading symbols from /usr/local/bin/vdr...done. [New LWP 26493] [New LWP 26492] [New LWP 26494] [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/libthread_db.so.1". Core was generated by `/usr/local/bin/vdr --config=/etc/vdr --epgfile=/tmp/epg.data --grab=/dev/shm --'. Program terminated with signal 11, Segmentation fault. #0 skipspace (s=0x40800000 <Address 0x40800000 out of bounds>) at tools.h:196 196 if ((uchar)*s > ' ') // most strings don't have any leading space, so handle this case as fast as possible (gdb) bt #0 skipspace (s=0x40800000 <Address 0x40800000 out of bounds>) at tools.h:196 #1 isempty (s=0x40800000 <Address 0x40800000 out of bounds>) at tools.c:249 #2 0x00000000004a1eb9 in FromString (s=0x2e531d2 "1 01 deu 4:3", this=0x2e4aba0) at epg.c:36 #3 cComponents::SetComponent (this=<optimized out>, Index=0, s=s@entry=0x2e531d2 "1 01 deu 4:3") at epg.c:81 #4 0x00000000004a40f3 in cEvent::Parse (this=0x2e43360, s=<optimized out>) at epg.c:495 #5 0x00000000004e9ea6 in cRecordingInfo::Read (this=0x2e2d110, f=f@entry=0x2e2c330) at recording.c:468 #6 0x00000000004eb4e3 in cRecording::cRecording (this=0x2e2c650, FileName=0x2e4c15c "Sex_and_the_City_2/2012-11-19.20.10.27-0.rec") at recording.c:723 #7 0x00000000004eceb1 in cRecordings::ScanVideoDir (this=0x7fe7c0 <Recordings>, DirName=0x2e412b0 "/remote/vdr/Sex_and_the_City_2", Foreground=false, LinkLevel=0) at recording.c:1165 #8 0x00000000004ed32c in cRecordings::ScanVideoDir (this=0x7fe7c0 <Recordings>, DirName=0x2e25ff0 "/remote/vdr", Foreground=false, LinkLevel=0) at recording.c:1180 #9 0x000000000052694e in cThread::StartThread (Thread=0x7fe7e0 <Recordings+32>) at thread.c:262 #10 0x00006e6b7ce69406 in start_thread () from /lib/libpthread.so.0.9.32 #11 0x00006e6b7ce61885 in clone () from /lib/libpthread.so.0.9.32 #12 0x0000000000000000 in ?? () --snip--
does anybody see what is wrong here ?
On 29 November 2012 15:17, Dieter Bloms vdr@bloms.de wrote:
does anybody see what is wrong here ?
Your choice of recording? ;)
#6 0x00000000004eb4e3 in cRecording::cRecording (this=0x2e2c650, FileName=0x2e4c15c "Sex_and_the_City_2/2012-11-19.20.10.27-0.rec") at recording.c:723
Hi,
On Thu, Nov 29, Dominic Evans wrote:
On 29 November 2012 15:17, Dieter Bloms vdr@bloms.de wrote:
does anybody see what is wrong here ?
Your choice of recording? ;)
#6 0x00000000004eb4e3 in cRecording::cRecording (this=0x2e2c650, FileName=0x2e4c15c "Sex_and_the_City_2/2012-11-19.20.10.27-0.rec") at recording.c:723
my wife did it. I've already moved this video outside from vdr directory, but then it segfaults at the next video. A second system based on opensuse runs fine, but I want to use alpine, because it is a lightweight distribution based on uClibc.
Hi,
Am 29.11.2012 16:17, schrieb Dieter Bloms:
Hello,
I've compiled vdr on alpinelinux 2.5.0 and get a segfault during start of vdr. Even without plugins I get this segfault (I didn't apply any patch to vdr sources). Vdr was started with the command:
/usr/local/bin/vdr --config=/etc/vdr --epgfile=/tmp/epg.data --grab=/dev/shm --log=3.1 --mute --no-kbd --user=root --video=/remote/vdr/
I've made a backtrace with gdb:
--snip-- vdrservernew:/tmp# gdb --core core /usr/local/bin/vdr GNU gdb (GDB) 7.5 Copyright (C) 2012 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later http://gnu.org/licenses/gpl.html This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-unknown-linux-gnu". For bug reporting instructions, please see: http://www.gnu.org/software/gdb/bugs/... Reading symbols from /usr/local/bin/vdr...done. [New LWP 26493] [New LWP 26492] [New LWP 26494] [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/libthread_db.so.1". Core was generated by `/usr/local/bin/vdr --config=/etc/vdr --epgfile=/tmp/epg.data --grab=/dev/shm --'. Program terminated with signal 11, Segmentation fault. #0 skipspace (s=0x40800000 <Address 0x40800000 out of bounds>) at tools.h:196 196 if ((uchar)*s > ' ') // most strings don't have any leading space, so handle this case as fast as possible (gdb) bt #0 skipspace (s=0x40800000 <Address 0x40800000 out of bounds>) at tools.h:196 #1 isempty (s=0x40800000 <Address 0x40800000 out of bounds>) at tools.c:249 #2 0x00000000004a1eb9 in FromString (s=0x2e531d2 "1 01 deu 4:3", this=0x2e4aba0) at epg.c:36
Looks like the pointer returned by sscanf is not valid:
32: bool tComponent::FromString(const char *s) 33: { 34: unsigned int Stream, Type; 35: int n = sscanf(s, "%X %02X %7s %a[^\n]", &Stream, &Type, language, &description); // 7 = MAXLANGCODE2 - 1 36: if (n != 4 || isempty(description)) { 37: free(description); 38: description = NULL; 39: } 40: stream = Stream; 41: type = Type; 42: return n >= 3; 43: }
What I would do: - set description to NULL before the sscanf - log all values returned by sscanf and compare it with the given string
Maybe a problem/different behaviour in the uClibc?
Lars.
#3 cComponents::SetComponent (this=<optimized out>, Index=0, s=s@entry=0x2e531d2 "1 01 deu 4:3") at epg.c:81 #4 0x00000000004a40f3 in cEvent::Parse (this=0x2e43360, s=<optimized out>) at epg.c:495 #5 0x00000000004e9ea6 in cRecordingInfo::Read (this=0x2e2d110, f=f@entry=0x2e2c330) at recording.c:468 #6 0x00000000004eb4e3 in cRecording::cRecording (this=0x2e2c650, FileName=0x2e4c15c "Sex_and_the_City_2/2012-11-19.20.10.27-0.rec") at recording.c:723 #7 0x00000000004eceb1 in cRecordings::ScanVideoDir (this=0x7fe7c0 <Recordings>, DirName=0x2e412b0 "/remote/vdr/Sex_and_the_City_2", Foreground=false, LinkLevel=0) at recording.c:1165 #8 0x00000000004ed32c in cRecordings::ScanVideoDir (this=0x7fe7c0 <Recordings>, DirName=0x2e25ff0 "/remote/vdr", Foreground=false, LinkLevel=0) at recording.c:1180 #9 0x000000000052694e in cThread::StartThread (Thread=0x7fe7e0 <Recordings+32>) at thread.c:262 #10 0x00006e6b7ce69406 in start_thread () from /lib/libpthread.so.0.9.32 #11 0x00006e6b7ce61885 in clone () from /lib/libpthread.so.0.9.32 #12 0x0000000000000000 in ?? () --snip--
does anybody see what is wrong here ?
Hi Lars,
thank you for the help!
On Fri, Nov 30, Lars Hanisch wrote:
32: bool tComponent::FromString(const char *s) 33: { 34: unsigned int Stream, Type; 35: int n = sscanf(s, "%X %02X %7s %a[^\n]", &Stream, &Type, language, &description); // 7 = MAXLANGCODE2 - 1 36: if (n != 4 || isempty(description)) { 37: free(description); 38: description = NULL; 39: } 40: stream = Stream; 41: type = Type; 42: return n >= 3; 43: }
What I would do:
- set description to NULL before the sscanf
- log all values returned by sscanf and compare it with the given string
I changed it this way:
--snip-- 32 bool tComponent::FromString(const char *s) 33 { 34 unsigned int Stream, Type; 35 description = NULL; 36 int n = sscanf(s, "%X %02X %7s %a[^\n]", &Stream, &Type, language, &description); // 7 = MAXLANGCODE2 - 1 37 esyslog("dbloms: "%X" "%02X" "%7s" "%a"", Stream, Type, language, description); 38 39 if (n != 4 || isempty(description)) { 40 free(description); 41 description = NULL; 42 } 43 stream = Stream; 44 type = Type; 45 return n >= 3; 46 } --snip--
but during compile I saw this message:
--snip-- g++ -g -O3 -Wall -Werror=overloaded-virtual -Wno-parentheses -c -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -DVDR_USER="root" -DLIRC_DEVICE="/var/run/lirc/lircd" -D_GNU_SOURCE -DVIDEODIR="/remote/vdr/video" -DCONFDIR="/etc/vdr/config" -DCACHEDIR="" -DRESDIR="" -DPLUGINDIR="/usr/src/vdr-1.7.32/PLUGINS/lib" -DLOCDIR="/usr/share/vdr/locale" -I/usr/include/freetype2 -I/usr/src/v4l-dvb/linux/include epg.c epg.c: In member function 'bool tComponent::FromString(const char*)': epg.c:37:3: warning: format '%a' expects argument of type 'double', but argument 6 has type 'char*' [-Wformat] --snip--
And after start in the logfile
--snip-- Nov 30 09:48:05 vdrservernew local1.err vdr: [4094] dbloms: "1" "01" " deu" "0x8.799b08p-1052" --snip--
I think %a in my esyslog call isn't correct, but it is used this way with the sscanf call and when I changed it with %s I don't see any log entry.
So how should the esyslog call look like ?
On Fri, Nov 30, 2012 at 11:00 AM, Dieter Bloms vdr@bloms.de wrote:
--snip-- g++ -g -O3 -Wall -Werror=overloaded-virtual -Wno-parentheses -c -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -DVDR_USER="root" -DLIRC_DEVICE="/var/run/lirc/lircd" -D_GNU_SOURCE -DVIDEODIR="/remote/vdr/video" -DCONFDIR="/etc/vdr/config" -DCACHEDIR="" -DRESDIR="" -DPLUGINDIR="/usr/src/vdr-1.7.32/PLUGINS/lib" -DLOCDIR="/usr/share/vdr/locale" -I/usr/include/freetype2 -I/usr/src/v4l-dvb/linux/include epg.c epg.c: In member function 'bool tComponent::FromString(const char*)': epg.c:37:3: warning: format '%a' expects argument of type 'double', but argument 6 has type 'char*' [-Wformat] --snip--
And after start in the logfile
--snip-- Nov 30 09:48:05 vdrservernew local1.err vdr: [4094] dbloms: "1" "01" " deu" "0x8.799b08p-1052" --snip--
I think %a in my esyslog call isn't correct, but it is used this way with the sscanf call and when I changed it with %s I don't see any log entry.
So how should the esyslog call look like ?
%a to print a char* is not right. char* is interpreted as double (see the compiler warning) . If you want to print the pointer 'description', then use %p.
The following code crashes on my box too. I dont know why.
$ ./a.out errno: 0 n=4 Stream:1 Type:1 lang:'deu' desc addr:'0x40800000' Segmentation fault $
In gdb: Program received signal SIGSEGV, Segmentation fault. 0x0016e50b in _IO_vfprintf_internal (s=0x2844e0, format=0x8048711 "desc:'%s'\n", ap=0xbffff3f4 "") at vfprintf.c:1614 1614 vfprintf.c: No such file or directory. in vfprintf.c (gdb) bt #0 0x0016e50b in _IO_vfprintf_internal (s=0x2844e0, format=0x8048711 "desc:'%s'\n", ap=0xbffff3f4 "") at vfprintf.c:1614 #1 0x00175160 in __printf (format=0x8048711 "desc:'%s'\n") at printf.c:35 #2 0x080485aa in FromString (s=0x804871c "1 01 deu 4:3") at fromstring.c:14 #3 0x080485ee in main (argc=1, argv=0xbffff514) at fromstring.c:22
--- snip ---
#include <stdio.h> #include <errno.h>
void FromString(const char *s) { unsigned int Stream, Type; char language[8] = {0}; char* description=NULL; int n = sscanf(s, "%X %02X %7s %a[^\n]", &Stream, &Type, language, &description); // 7 = MAXLANGCODE2 - 1 printf("errno: %d\n", errno); printf("n=%d\n", n); printf("Stream:%u Type:%u lang:'%s'\n", Stream, Type, language); printf("desc addr:'%p'\n", description); printf("desc:'%s'\n", description); // XXX crashes here }
int main(int argc, char* argv[]) { if (argc == 2) FromString((const char*)argv[1]); else FromString("1 01 deu 4:3");
return 0; }
----- snip -----
Hi,
On Fri, Nov 30, sundararaj reel wrote:
%a to print a char* is not right. char* is interpreted as double (see the compiler warning) . If you want to print the pointer 'description', then use %p.
with "esyslog("dbloms: "%X" "%02X" "%7s" "%p"", Stream, Type, language, description);" I get the following log entry:
--snip-- Nov 30 10:27:24 vdrservernew local1.err vdr: [7118] dbloms: "1" "01" " deu" "0x40800000" --snip--
The following code crashes on my box too. I dont know why.
did you do it on uClibc system or a glibc one ?
On Fri, Nov 30, 2012 at 11:31 AM, Dieter Bloms vdr@bloms.de wrote:
Hi,
On Fri, Nov 30, sundararaj reel wrote:
%a to print a char* is not right. char* is interpreted as double (see the compiler warning) . If you want to print the pointer 'description', then use %p.
with "esyslog("dbloms: "%X" "%02X" "%7s" "%p"", Stream, Type, language, description);" I get the following log entry:
--snip-- Nov 30 10:27:24 vdrservernew local1.err vdr: [7118] dbloms: "1" "01" " deu" "0x40800000" --snip--
The following code crashes on my box too. I dont know why.
did you do it on uClibc system or a glibc one ?
Ran that code on ubuntu 10.04.
$ /lib/libc.so.6 GNU C Library (Ubuntu EGLIBC 2.11.1-0ubuntu7) stable release version 2.11.1, by Roland McGrath et al. Copyright (C) 2009 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Compiled by GNU CC version 4.4.3. Compiled on a Linux >>2.6.24-27-server<< system on 2010-04-22. Available extensions: crypt add-on version 2.1 by Michael Glad and others GNU Libidn by Simon Josefsson Native POSIX Threads Library by Ulrich Drepper et al BIND-8.2.3-T5B For bug reporting instructions, please see: http://www.debian.org/Bugs/.
On Fri, Nov 30, 2012 at 11:00:52AM +0100, Dieter Bloms wrote:
I changed it this way:
--snip-- 32 bool tComponent::FromString(const char *s) 33 { 34 unsigned int Stream, Type; 35 description = NULL; 36 int n = sscanf(s, "%X %02X %7s %a[^\n]", &Stream, &Type, language, &description); // 7 = MAXLANGCODE2 - 1 37 esyslog("dbloms: "%X" "%02X" "%7s" "%a"", Stream, Type, language, description); 38 39 if (n != 4 || isempty(description)) { 40 free(description); 41 description = NULL; 42 } 43 stream = Stream; 44 type = Type; 45 return n >= 3; 46 } --snip--
IMHO the %a should become %s in esyslog() whereas in sscanf() the %a should become %as for the GNU extension of dynamically allocating string conversions.
Werner
Hi Werner,
On Fri, Nov 30, Dr. Werner Fink wrote:
On Fri, Nov 30, 2012 at 11:00:52AM +0100, Dieter Bloms wrote:
I changed it this way:
--snip-- 32 bool tComponent::FromString(const char *s) 33 { 34 unsigned int Stream, Type; 35 description = NULL; 36 int n = sscanf(s, "%X %02X %7s %a[^\n]", &Stream, &Type, language, &description); // 7 = MAXLANGCODE2 - 1 37 esyslog("dbloms: "%X" "%02X" "%7s" "%a"", Stream, Type, language, description); 38 39 if (n != 4 || isempty(description)) { 40 free(description); 41 description = NULL; 42 } 43 stream = Stream; 44 type = Type; 45 return n >= 3; 46 } --snip--
IMHO the %a should become %s in esyslog() whereas in sscanf() the %a should become %as for the GNU extension of dynamically allocating string conversions.
Now I've the following code:
--snip-- 25 cString tComponent::ToString(void) 26 { 27 char buffer[256]; 28 snprintf(buffer, sizeof(buffer), "%X %02X %s %s", stream, type, language, description ? description : ""); 29 return buffer; 30 } 31 32 bool tComponent::FromString(const char *s) 33 { 34 unsigned int Stream, Type; 35 description = NULL; 36 int n = sscanf(s, "%X %02X %7s %as[^\n]", &Stream, &Type, language, &description); // 7 = MAXLANGCODE2 - 1 37 esyslog("dbloms: "%X" "%02X" "%7s" "%s"", Stream, Type, language, description); 38 39 if (n != 4 || isempty(description)) { 40 free(description); 41 description = NULL; 42 } 43 stream = Stream; 44 type = Type; 45 return n >= 3; 46 } --snip--
and get a core dump with this:
--snip-- vdrservernew:/tmp# gdb --core /tmp/core /usr/local/bin/vdr GNU gdb (GDB) 7.5 Copyright (C) 2012 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later http://gnu.org/licenses/gpl.html This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-unknown-linux-gnu". For bug reporting instructions, please see: http://www.gnu.org/software/gdb/bugs/... Reading symbols from /usr/local/bin/vdr...done. [New LWP 8986] [New LWP 8985] [New LWP 8987] [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/libthread_db.so.1". Core was generated by `/usr/local/bin/vdr --config=/etc/vdr --epgfile=/tmp/epg.data --grab=/dev/shm --'. Program terminated with signal 11, Segmentation fault. #0 0x00006b2476b263b3 in strnlen () from /lib/libc.so.0.9.32 (gdb) bt #0 0x00006b2476b263b3 in strnlen () from /lib/libc.so.0.9.32 #1 0x00006b2476b1ff56 in ?? () from /lib/libc.so.0.9.32 #2 0x00006b2476b1d5dc in vsnprintf () from /lib/libc.so.0.9.32 #3 0x00006b2476b14c29 in vsyslog () from /lib/libc.so.0.9.32 #4 0x000000000052e510 in syslog_with_tid (priority=3, format=0x551ab8 "dbloms: "%X" "%02X" "%7s" "%s"") at tools.c:40 #5 0x00000000004a1e4e in FromString (s=<optimized out>, this=0x3dabc20) at epg.c:37 #6 cComponents::SetComponent (this=<optimized out>, Index=<optimized out>, s=s@entry=0x3daaaa2 "1 01 deu 4:3") at epg.c:84 #7 0x00000000004a4163 in cEvent::Parse (this=0x3d9f4d0, s=<optimized out>) at epg.c:498 #8 0x00000000004e9f16 in cRecordingInfo::Read (this=0x3da8640, f=f@entry=0x3d9f840) at recording.c:468 #9 0x00000000004eb553 in cRecording::cRecording (this=0x3da05c0, FileName=0x3d8aa7c "Sex_and_the_City_2/2012-11-19.20.10.27-0.rec") at recording.c:723 #10 0x00000000004ecf21 in cRecordings::ScanVideoDir (this=0x7fe880 <Recordings>, DirName=0x3d9d4c0 "/remote/vdr/Sex_and_the_City_2", Foreground=false, LinkLevel=0) at recording.c:1165 #11 0x00000000004ed39c in cRecordings::ScanVideoDir (this=0x7fe880 <Recordings>, DirName=0x3d83a20 "/remote/vdr", Foreground=false, LinkLevel=0) at recording.c:1180 #12 0x00000000005269be in cThread::StartThread (Thread=0x7fe8a0 <Recordings+32>) at thread.c:262 #13 0x00006b247844a406 in start_thread () from /lib/libpthread.so.0.9.32 #14 0x00006b2478442885 in clone () from /lib/libpthread.so.0.9.32 #15 0x0000000000000000 in ?? () (gdb) --snip--
On Fri, Nov 30, 2012 at 12:08:53PM +0100, Dieter Bloms wrote:
Hi Werner,
--snip-- 25 cString tComponent::ToString(void) 26 { 27 char buffer[256]; 28 snprintf(buffer, sizeof(buffer), "%X %02X %s %s", stream, type, language, description ? description : ""); 29 return buffer; 30 } 31 32 bool tComponent::FromString(const char *s) 33 { 34 unsigned int Stream, Type; 35 description = NULL; 36 int n = sscanf(s, "%X %02X %7s %as[^\n]", &Stream, &Type, language, &description); // 7 = MAXLANGCODE2 - 1 37 esyslog("dbloms: "%X" "%02X" "%7s" "%s"", Stream, Type, language, description); 38 39 if (n != 4 || isempty(description)) { 40 free(description); 41 description = NULL; 42 } 43 stream = Stream; 44 type = Type; 45 return n >= 3; 46 } --snip--
and get a core dump with this:
--snip-- vdrservernew:/tmp# gdb --core /tmp/core /usr/local/bin/vdr GNU gdb (GDB) 7.5 Copyright (C) 2012 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later http://gnu.org/licenses/gpl.html This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-unknown-linux-gnu". For bug reporting instructions, please see: http://www.gnu.org/software/gdb/bugs/... Reading symbols from /usr/local/bin/vdr...done. [New LWP 8986] [New LWP 8985] [New LWP 8987] [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/libthread_db.so.1". Core was generated by `/usr/local/bin/vdr --config=/etc/vdr --epgfile=/tmp/epg.data --grab=/dev/shm --'. Program terminated with signal 11, Segmentation fault. #0 0x00006b2476b263b3 in strnlen () from /lib/libc.so.0.9.32 (gdb) bt #0 0x00006b2476b263b3 in strnlen () from /lib/libc.so.0.9.32 #1 0x00006b2476b1ff56 in ?? () from /lib/libc.so.0.9.32 #2 0x00006b2476b1d5dc in vsnprintf () from /lib/libc.so.0.9.32 #3 0x00006b2476b14c29 in vsyslog () from /lib/libc.so.0.9.32 #4 0x000000000052e510 in syslog_with_tid (priority=3, format=0x551ab8 "dbloms: "%X" "%02X" "%7s" "%s"") at tools.c:40 #5 0x00000000004a1e4e in FromString (s=<optimized out>, this=0x3dabc20) at epg.c:37 #6 cComponents::SetComponent (this=<optimized out>, Index=<optimized out>, s=s@entry=0x3daaaa2 "1 01 deu 4:3") at epg.c:84 #7 0x00000000004a4163 in cEvent::Parse (this=0x3d9f4d0, s=<optimized out>) at epg.c:498 #8 0x00000000004e9f16 in cRecordingInfo::Read (this=0x3da8640, f=f@entry=0x3d9f840) at recording.c:468 #9 0x00000000004eb553 in cRecording::cRecording (this=0x3da05c0, FileName=0x3d8aa7c "Sex_and_the_City_2/2012-11-19.20.10.27-0.rec") at recording.c:723 #10 0x00000000004ecf21 in cRecordings::ScanVideoDir (this=0x7fe880 <Recordings>, DirName=0x3d9d4c0 "/remote/vdr/Sex_and_the_City_2", Foreground=false, LinkLevel=0) at recording.c:1165 #11 0x00000000004ed39c in cRecordings::ScanVideoDir (this=0x7fe880 <Recordings>, DirName=0x3d83a20 "/remote/vdr", Foreground=false, LinkLevel=0) at recording.c:1180 #12 0x00000000005269be in cThread::StartThread (Thread=0x7fe8a0 <Recordings+32>) at thread.c:262 #13 0x00006b247844a406 in start_thread () from /lib/libpthread.so.0.9.32 #14 0x00006b2478442885 in clone () from /lib/libpthread.so.0.9.32 #15 0x0000000000000000 in ?? () (gdb) --snip--
Maybe some more checks are required as if n != 4 this could be that one of the variables are not used and therefore not initialized.
Before sscanf() this could be a `memset(language, 0, sizeof(language));' or more simple a `*language = 0;' depending on the type of language. Also the code
if (n != 4 || isempty(description)) { free(description); description = NULL; }
could become
if (n != 4 || isempty(description)) { if (description) free(description); description = NULL; }
as well as the line
esyslog("dbloms: "%X" "%02X" "%7s" "%s"", Stream, Type, language, description);
may look like
esyslog("dbloms: "%X" "%02X" "%7s" "%s"", Stream, Type, language, description ? description : "");
Werner
Hi,
On Fri, Nov 30, Dr. Werner Fink wrote:
Maybe some more checks are required as if n != 4 this could be that one of the variables are not used and therefore not initialized.
Before sscanf() this could be a `memset(language, 0, sizeof(language));' or more simple a `*language = 0;' depending on the type of language. Also the code
if (n != 4 || isempty(description)) { free(description); description = NULL; }
could become
if (n != 4 || isempty(description)) { if (description) free(description); description = NULL; }
as well as the line
esyslog("dbloms: "%X" "%02X" "%7s" "%s"", Stream, Type, language, description);
may look like
esyslog("dbloms: "%X" "%02X" "%7s" "%s"", Stream, Type, language, description ? description : "");
may code looks like:
--snip-- bool tComponent::FromString(const char *s) { unsigned int Stream, Type; description = NULL; int n = sscanf(s, "%X %02X %7s %as[^\n]", &Stream, &Type, language, &description); // 7 = MAXLANGCODE2 - 1 esyslog("dbloms: "%X" "%02X" "%7s" "%s"", Stream, Type, language, description ? description : "");
if (n != 4 || isempty(description)) { if (description) free(description); description = NULL; } stream = Stream; type = Type; return n >= 3; } --snip--
and I get a core dump like:
--snip-- vdrservernew:/usr/src/vdr-1.7.32# gdb --core /tmp/core /usr/local/bin/vdr GNU gdb (GDB) 7.5 Copyright (C) 2012 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later http://gnu.org/licenses/gpl.html This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-unknown-linux-gnu". For bug reporting instructions, please see: http://www.gnu.org/software/gdb/bugs/... Reading symbols from /usr/local/bin/vdr...done. [New LWP 2829] [New LWP 2830] [New LWP 2828] [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/libthread_db.so.1". Core was generated by `/usr/local/bin/vdr --config=/etc/vdr --epgfile=/tmp/epg.data --grab=/dev/shm --'. Program terminated with signal 11, Segmentation fault. #0 0x0000799a5fbbe3b3 in strnlen () from /lib/libc.so.0.9.32 (gdb) bt #0 0x0000799a5fbbe3b3 in strnlen () from /lib/libc.so.0.9.32 #1 0x0000799a5fbb7f56 in ?? () from /lib/libc.so.0.9.32 #2 0x0000799a5fbb55dc in vsnprintf () from /lib/libc.so.0.9.32 #3 0x0000799a5fbacc29 in vsyslog () from /lib/libc.so.0.9.32 #4 0x000000000052e570 in syslog_with_tid (priority=3, format=0x551b18 "dbloms: "%X" "%02X" "%7s" "%s"") at tools.c:40 #5 0x00000000004a1bbd in tComponent::FromString (this=0x22a24b0, s=<optimized out>) at epg.c:37 #6 0x00000000004a4197 in SetComponent (s=<optimized out>, Index=0, this=0x22ad550) at epg.c:85 #7 cEvent::Parse (this=<optimized out>, s=<optimized out>) at epg.c:499 #8 0x00000000004e9f76 in cRecordingInfo::Read (this=0x22a50e0, f=f@entry=0x22a1f00) at recording.c:468 #9 0x00000000004eb5b3 in cRecording::cRecording (this=0x22a2210, FileName=0x22a0fdc "Sex_and_the_City_2/2012-11-19.20.10.27-0.rec") at recording.c:723 #10 0x00000000004ecf81 in cRecordings::ScanVideoDir (this=0x7fe900 <Recordings>, DirName=0x229aca0 "/remote/vdr/Sex_and_the_City_2", Foreground=false, LinkLevel=0) at recording.c:1165 #11 0x00000000004ed3fc in cRecordings::ScanVideoDir (this=0x7fe900 <Recordings>, DirName=0x2285390 "/remote/vdr", Foreground=false, LinkLevel=0) at recording.c:1180 #12 0x0000000000526a1e in cThread::StartThread (Thread=0x7fe920 <Recordings+32>) at thread.c:262 #13 0x0000799a614e2406 in start_thread () from /lib/libpthread.so.0.9.32 #14 0x0000799a614da885 in clone () from /lib/libpthread.so.0.9.32 #15 0x0000000000000000 in ?? () (gdb) --snip--
Am 2012-11-30 10:17, schrieb Lars Hanisch:
Looks like the pointer returned by sscanf is not valid:
32: bool tComponent::FromString(const char *s) 33: { 34: unsigned int Stream, Type; 35: int n = sscanf(s, "%X %02X %7s %a[^\n]", &Stream, &Type, language, &description); // 7 = MAXLANGCODE2 - 1 36: if (n != 4 || isempty(description)) { 37: free(description); 38: description = NULL; 39: } 40: stream = Stream; 41: type = Type; 42: return n >= 3; 43: }
From man sscanf:
The GNU C library supports a nonstandard extension that causes the library to dynamically allocate a string of sufficient size for input strings for the %s and %a[range] conversion specifiers.
This is the reason why it doesn't work with ulibc.
Gerald
Am 30.11.2012 11:32, schrieb Gerald Dachs:
Am 2012-11-30 10:17, schrieb Lars Hanisch:
Looks like the pointer returned by sscanf is not valid:
32: bool tComponent::FromString(const char *s) 33: { 34: unsigned int Stream, Type; 35: int n = sscanf(s, "%X %02X %7s %a[^\n]", &Stream, &Type, language, &description); // 7 = MAXLANGCODE2 - 1 36: if (n != 4 || isempty(description)) { 37: free(description); 38: description = NULL; 39: } 40: stream = Stream; 41: type = Type; 42: return n >= 3; 43: }
From man sscanf:
The GNU C library supports a nonstandard extension that causes the library to dynamically allocate a string of sufficient size for input strings for the %s and %a[range] conversion specifiers.This is the reason why it doesn't work with ulibc.
Then there should be a malloc or something similiar for description:
32: bool tComponent::FromString(const char *s) 33: { 34: unsigned int Stream, Type; description = malloc(strlen(s)); description[0] = 0; 35: int n = sscanf(s, "%X %02X %7s %a[^\n]", &Stream, &Type, language, &description); // 7 = MAXLANGCODE2 - 1 36: if (n != 4 || isempty(description)) { 37: free(description); 38: description = NULL; 39: } 40: stream = Stream; 41: type = Type; 42: return n >= 3; 43: }
A check for description != NULL before the free call is not needed.
But this is not the only place in the vdr code, where %a is used...
Lars.
Gerald
vdr mailing list vdr@linuxtv.org http://www.linuxtv.org/cgi-bin/mailman/listinfo/vdr
In article 50BA09CC.2040104@flensrocker.de you write:
Am 30.11.2012 11:32, schrieb Gerald Dachs:
Am 2012-11-30 10:17, schrieb Lars Hanisch:
Looks like the pointer returned by sscanf is not valid:
32: bool tComponent::FromString(const char *s) 33: { 34: unsigned int Stream, Type; 35: int n = sscanf(s, "%X %02X %7s %a[^\n]", &Stream, &Type, language, &description); // 7 = MAXLANGCODE2 - 1 36: if (n != 4 || isempty(description)) { 37: free(description); 38: description = NULL; 39: } 40: stream = Stream; 41: type = Type; 42: return n >= 3; 43: }
From man sscanf:
The GNU C library supports a nonstandard extension that causes the library to dynamically allocate a string of sufficient size for input strings for the %s and %a[range] conversion specifiers.This is the reason why it doesn't work with ulibc.
Then there should be a malloc or something similiar for description:
32: bool tComponent::FromString(const char *s) 33: { 34: unsigned int Stream, Type; description = malloc(strlen(s)); description[0] = 0; 35: int n = sscanf(s, "%X %02X %7s %a[^\n]", &Stream, &Type, language, &description); // 7 = MAXLANGCODE2 - 1 36: if (n != 4 || isempty(description)) { 37: free(description); 38: description = NULL; 39: } 40: stream = Stream; 41: type = Type; 42: return n >= 3; 43: }
A check for description != NULL before the free call is not needed.
But this is not the only place in the vdr code, where %a is used...
Btw FreeBSD has the same problem (no *scanf %a in libc), so you could try taking the FreeBSD patches and replacing
#ifdef __FreeBSD__
by
#if defined(__FreeBSD__) || defined(__UCLIBC__)
in those parts handling %a here:
http://svnweb.freebsd.org/ports/head/multimedia/vdr/files/patch-vdr-1.7.28_F...
A few plugins are affected too: (of those we have in FreeBSD ports)
eepg:
http://svnweb.freebsd.org/ports/head/multimedia/vdr-plugin-eepg/files/patch-...
infosatepg:
http://svnweb.freebsd.org/ports/head/multimedia/vdr-plugin-infosatepg/files/...
ttxtsubs:
http://svnweb.freebsd.org/ports/head/multimedia/vdr-plugin-ttxtsubs/files/pa...
HTH, :) Juergen
PS: I think I never sent the FreeBSD patches to Klaus the last few times I updated them, atm FreeBSD ports is behind again (still at vdr 1.7.29), when I get around catching up to the latest version I can send the updated patches if you are interested, Klaus? A few more 1.7.29 patches are in here:
http://svnweb.freebsd.org/ports/head/multimedia/vdr/files/
(I think I did send FreeBSD patches to those plugin maintainers that may still be active some time ago, haven't heard back from many tho.)
On 01.12.2012 21:14, Juergen Lock wrote:
In article 50BA09CC.2040104@flensrocker.de you write:
Am 30.11.2012 11:32, schrieb Gerald Dachs:
Am 2012-11-30 10:17, schrieb Lars Hanisch:
Looks like the pointer returned by sscanf is not valid:
32: bool tComponent::FromString(const char *s) 33: { 34: unsigned int Stream, Type; 35: int n = sscanf(s, "%X %02X %7s %a[^\n]", &Stream, &Type, language, &description); // 7 = MAXLANGCODE2 - 1 36: if (n != 4 || isempty(description)) { 37: free(description); 38: description = NULL; 39: } 40: stream = Stream; 41: type = Type; 42: return n >= 3; 43: }
From man sscanf:
The GNU C library supports a nonstandard extension that causes the library to dynamically allocate a string of sufficient size for input strings for the %s and %a[range] conversion specifiers.This is the reason why it doesn't work with ulibc.
Then there should be a malloc or something similiar for description:
32: bool tComponent::FromString(const char *s) 33: { 34: unsigned int Stream, Type; description = malloc(strlen(s)); description[0] = 0; 35: int n = sscanf(s, "%X %02X %7s %a[^\n]", &Stream, &Type, language, &description); // 7 = MAXLANGCODE2 - 1 36: if (n != 4 || isempty(description)) { 37: free(description); 38: description = NULL; 39: } 40: stream = Stream; 41: type = Type; 42: return n >= 3; 43: }
A check for description != NULL before the free call is not needed.
But this is not the only place in the vdr code, where %a is used...
Btw FreeBSD has the same problem (no *scanf %a in libc), so you could try taking the FreeBSD patches and replacing
#ifdef __FreeBSD__
by
#if defined(__FreeBSD__) || defined(__UCLIBC__)
in those parts handling %a here:
http://svnweb.freebsd.org/ports/head/multimedia/vdr/files/patch-vdr-1.7.28_F...
A few plugins are affected too: (of those we have in FreeBSD ports)
eepg:
http://svnweb.freebsd.org/ports/head/multimedia/vdr-plugin-eepg/files/patch-...
infosatepg:
http://svnweb.freebsd.org/ports/head/multimedia/vdr-plugin-infosatepg/files/...
ttxtsubs:
http://svnweb.freebsd.org/ports/head/multimedia/vdr-plugin-ttxtsubs/files/pa...
HTH, :) Juergen
PS: I think I never sent the FreeBSD patches to Klaus the last few times I updated them, atm FreeBSD ports is behind again (still at vdr 1.7.29), when I get around catching up to the latest version I can send the updated patches if you are interested, Klaus?
Well, in all honesty (and without meaning any offense or disrespect), I wouldn't like to have all these "#if ..." spread around the VDR source. For instance, things like a missing getline() function should not be patched right into the tools.c code, but rather be put into a separate file, maybe named oscompat.[hc]. In that file, depending on the OS in use, a local implementation of getline() could be implemented, and tools.c (like any other file that needs OS compatibility stuff) could just #include "oscompat.h" and the Makefile could link oscompat.o into the final executable.
There are also some patches that don't, at first glance, look like they would be BSD specific, like those in plugin.c. Are these just a different way of handling things (and would this also work on Linux)? Or is this whole shebang handled differently in BSD?
Well, finally for the root of this whole discussion: I really like the "%a" format character in sscanf(), because it is so simple and straightforward. I don't see why other libcs don't implement this, and I wouldn't want to have all that bulk in such areas. So I suggest you either get the libcs on those platforms to implement this (and thus solve the problem once and for all), or put your own version of sscanf() into the proposed oscompat.c and handle "%a" properly in there.
A few more 1.7.29 patches are in here:
http://svnweb.freebsd.org/ports/head/multimedia/vdr/files/
(I think I did send FreeBSD patches to those plugin maintainers that may still be active some time ago, haven't heard back from many tho.)
Klaus
On Sun, Dec 02, 2012 at 02:19:44PM +0100, Klaus Schmidinger wrote:
On 01.12.2012 21:14, Juergen Lock wrote:
In article 50BA09CC.2040104@flensrocker.de you write:
Am 30.11.2012 11:32, schrieb Gerald Dachs:
Am 2012-11-30 10:17, schrieb Lars Hanisch:
Looks like the pointer returned by sscanf is not valid:
32: bool tComponent::FromString(const char *s) 33: { 34: unsigned int Stream, Type; 35: int n = sscanf(s, "%X %02X %7s %a[^\n]", &Stream, &Type, language, &description); // 7 = MAXLANGCODE2 - 1 36: if (n != 4 || isempty(description)) { 37: free(description); 38: description = NULL; 39: } 40: stream = Stream; 41: type = Type; 42: return n >= 3; 43: }
From man sscanf:
The GNU C library supports a nonstandard extension that causes the library to dynamically allocate a string of sufficient size for input strings for the %s and %a[range] conversion specifiers.This is the reason why it doesn't work with ulibc.
Then there should be a malloc or something similiar for description:
32: bool tComponent::FromString(const char *s) 33: { 34: unsigned int Stream, Type; description = malloc(strlen(s)); description[0] = 0; 35: int n = sscanf(s, "%X %02X %7s %a[^\n]", &Stream, &Type, language, &description); // 7 = MAXLANGCODE2 - 1 36: if (n != 4 || isempty(description)) { 37: free(description); 38: description = NULL; 39: } 40: stream = Stream; 41: type = Type; 42: return n >= 3; 43: }
A check for description != NULL before the free call is not needed.
But this is not the only place in the vdr code, where %a is used...
Btw FreeBSD has the same problem (no *scanf %a in libc), so you could try taking the FreeBSD patches and replacing
#ifdef __FreeBSD__
by
#if defined(__FreeBSD__) || defined(__UCLIBC__)
in those parts handling %a here:
http://svnweb.freebsd.org/ports/head/multimedia/vdr/files/patch-vdr-1.7.28_F...
A few plugins are affected too: (of those we have in FreeBSD ports)
eepg:
http://svnweb.freebsd.org/ports/head/multimedia/vdr-plugin-eepg/files/patch-...
infosatepg:
http://svnweb.freebsd.org/ports/head/multimedia/vdr-plugin-infosatepg/files/...
ttxtsubs:
http://svnweb.freebsd.org/ports/head/multimedia/vdr-plugin-ttxtsubs/files/pa...
HTH, :) Juergen
PS: I think I never sent the FreeBSD patches to Klaus the last few times I updated them, atm FreeBSD ports is behind again (still at vdr 1.7.29), when I get around catching up to the latest version I can send the updated patches if you are interested, Klaus?
Well, in all honesty (and without meaning any offense or disrespect), I wouldn't like to have all these "#if ..." spread around the VDR source. For instance, things like a missing getline() function should not be patched right into the tools.c code, but rather be put into a separate file, maybe named oscompat.[hc]. In that file, depending on the OS in use, a local implementation of getline() could be implemented, and tools.c (like any other file that needs OS compatibility stuff) could just #include "oscompat.h" and the Makefile could link oscompat.o into the final executable.
There are also some patches that don't, at first glance, look like they would be BSD specific, like those in plugin.c. Are these just a different way of handling things (and would this also work on Linux)? Or is this whole shebang handled differently in BSD?
Hm I don't remember where that particular patch came from but I _think_ the issue there is just that on BSD like errno with syscalls, dlerror() isn't reset when dlopen() or dlsym() are successful (return non-NULL), and yes the idea is that the patch should work on Linux too, which is why we didn't put in #ifdef __FreeBSD__. (Not sure anyone actually tested this on Linux yet tho.)
Well, finally for the root of this whole discussion: I really like the "%a" format character in sscanf(), because it is so simple and straightforward. I don't see why other libcs don't implement this, and I wouldn't want to have all that bulk in such areas. So I suggest you either get the libcs on those platforms to implement this (and thus solve the problem once and for all),
Uhm. :) %a surely isn't standardized anywhere so it would be called a prime example of a Linuxism, even if it may be an useful one. But you can't really expect everyone else to implement it too...
or put your own version of sscanf() into the proposed oscompat.c and handle "%a" properly in there.
Well, not sure when I would get to _that_... (As just taking glibc's *scanf() will probably end up needing a lot of other code from glibc too.) Guess I'll just leave those parts of the patches in FreeBSD ports for now then, unless someone else comes up with code for this before me.
Tho getline() btw is less important anyway, it's only missing on FreeBSD 7.x where most of the ways to get dvb drivers don't work yet so vdr would pretty much only be useful as a client instance or for IPTV there. (_And_ FreeBSD 7.x will be EOL'd soon too.)
Oh and btw the receiver.c patch would affect Linux too if building with llvm/clang, which ignores accesses thru a NULL pointer constant and instead prints a warning. And the tools.c patch for the cCharSetConv destructor looks like an actual bug, iconv_close() shouldn't be called with (iconv_t)-1.
A few more 1.7.29 patches are in here:
http://svnweb.freebsd.org/ports/head/multimedia/vdr/files/
(I think I did send FreeBSD patches to those plugin maintainers that may still be active some time ago, haven't heard back from many tho.)
Klaus
...and thanx for VDR! :)
Juergen
On Sun, Dec 02, 2012 at 08:58:31PM +0100, Juergen Lock wrote:
On Sun, Dec 02, 2012 at 02:19:44PM +0100, Klaus Schmidinger wrote:
On 01.12.2012 21:14, Juergen Lock wrote:
In article 50BA09CC.2040104@flensrocker.de you write:
Am 30.11.2012 11:32, schrieb Gerald Dachs:
Am 2012-11-30 10:17, schrieb Lars Hanisch:
[...] And the tools.c patch for the cCharSetConv destructor looks like an actual bug, iconv_close() shouldn't be called with (iconv_t)-1.
Ah sorry that patch isn't in ports yet, and now that I think of it it only occured when testing the epgfixer plugin which doesn't quite work properly yet anyway. But I guess it wouldn't hurt applying anyway so here it is:
--- tools.c.orig +++ tools.c @@ -842,7 +842,8 @@ cCharSetConv::cCharSetConv(const char *F cCharSetConv::~cCharSetConv() { free(result); - iconv_close(cd); + if (cd != (iconv_t)-1) + iconv_close(cd); }
void cCharSetConv::SetSystemCharacterTable(const char *CharacterTable)
Thanx again, :) Juergen