Date: Sat, 10 Oct 2009 04:44:44 GMT From: TerryP <BigBoss1964@gmail.com> To: freebsd-gnats-submit@FreeBSD.org Subject: bin/139470: pkg_delete segfaults on '@pkgdep ' in +CONTENTS file Message-ID: <200910100444.n9A4iift082097@www.freebsd.org> Resent-Message-ID: <200910100450.n9A4o7rh094791@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 139470
>Category: bin
>Synopsis: pkg_delete segfaults on '@pkgdep ' in +CONTENTS file
>Confidential: no
>Severity: serious
>Priority: low
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Sat Oct 10 04:50:06 UTC 2009
>Closed-Date:
>Last-Modified:
>Originator: TerryP
>Release: 7-stable / RELENG_7
>Organization:
N/A
>Environment:
FreeBSD dixie.launchmodem.com 7.2-STABLE FreeBSD 7.2-STABLE #4: Thu Jun 25 22:05:05 UTC 2009 root@dixie.launchmodem.com:/usr/obj/usr/src/sys/VIPER i386
>Description:
While running make deinstall in /usr/ports/graphics/ImageMagick, pkg_delete crashes with the following output:
pkg_delete: package 'ImageMagick-6.5.5.7' is required by these other packages
and may not be deinstalled (but I'll delete it anyway):
inkscape-0.46_6
libxine-1.1.16.3_1
Segmentation fault
I've read the source code in /usr/src/usr.sbin/pkg_install and found out what happened. The list that is processed contains a NULL entry, which is later passed onto strcmp() as part of the processing; you can get the exact backtrace through gdb. It looks like the origin of the NULL in question, is found within the function read_plist() from pkg_install/lib/plist.c. In this function, the lines are read from the currently installed /var/db/pkg/pkgname/+CONTENTS file. If the last character in the parsed line, is a space then it is replaced with a \0 terminator, until trailing spaces are blotted out. Within the +CONTENTS file for the installed ImageMagick here, is a line like this: '@pkgdep ', note the trailing space.
Parsing that line results in this code being executed as part of read_plist():
if (*cp == '\0') {
cp = NULL;
goto bottom;
}
the NULL gets passed on, until it eventually becomes an argument to strcmp(), which obviously is a cork poping event!
I am not familiar with the syntax of directives used in the +CONTENTS files, but I know that pkg_delete should never crash ;). There is probably a problem with the ImageMagick port or the code that generates the packing list in +CONTENTS.
>How-To-Repeat:
I believe all you would have to do, is run pkg_delete -f pkgname, where pkgname has a /var/db/pkg/pkgname/+CONTENTS file with a bad directive comparable to this one: '@pkgdep ', again note the trailing space and lack of an argument to the pkgdep command.
This was found while trying to deinstall ImageMagick-6.5.5.7.
>Fix:
0.) Decide how read_plist() should deal with parsing errors
1.) Generate warning about +CONTENTS having a bad line.
2.) Do anything except pass on a NULL pointer further down the chain.
My advice is that the bad directive should generate a warning and be ignored, or the whole thing should just exit with an error message.
Attached is a unified diff/patch file that makes it exit with an error message instead of segfault. Someone who works on FreeBSD is a much better judge of what behaviour is actually desired here, so I will leave the wisdom department to y'all.
cd /usr/src/usr.sbin/pkg_install
patch < /path/to/patchfile
Patch attached with submission follows:
--- lib/plist.c 2009-10-10 04:20:46.000000000 +0000
+++ lib/plist.c.changed 2009-10-10 04:28:50.000000000 +0000
@@ -284,8 +284,8 @@
goto bottom;
}
if (*cp == '\0') {
- cp = NULL;
- goto bottom;
+ errx(2, "%s: error in line '%s', the +CONTENTS file for %s is probably bad",
+ __func__, pline, pkg->name);
}
if (cmd == PLIST_COMMENT && sscanf(cp, "PKG_FORMAT_REVISION:%d.%d\n",
&major, &minor) == 2) {
>Release-Note:
>Audit-Trail:
>Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200910100444.n9A4iift082097>
