From nobody@FreeBSD.org  Sat Oct 10 04:44:45 2009
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id 86669106566B
	for <freebsd-gnats-submit@FreeBSD.org>; Sat, 10 Oct 2009 04:44:45 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21])
	by mx1.freebsd.org (Postfix) with ESMTP id 74BDD8FC1D
	for <freebsd-gnats-submit@FreeBSD.org>; Sat, 10 Oct 2009 04:44:45 +0000 (UTC)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.14.3/8.14.3) with ESMTP id n9A4iicQ082098
	for <freebsd-gnats-submit@FreeBSD.org>; Sat, 10 Oct 2009 04:44:44 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.14.3/8.14.3/Submit) id n9A4iift082097;
	Sat, 10 Oct 2009 04:44:44 GMT
	(envelope-from nobody)
Message-Id: <200910100444.n9A4iift082097@www.freebsd.org>
Date: Sat, 10 Oct 2009 04:44:44 GMT
From: TerryP <BigBoss1964@gmail.com>
To: freebsd-gnats-submit@FreeBSD.org
Subject: pkg_delete segfaults on '@pkgdep ' in +CONTENTS file
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         139470
>Category:       bin
>Synopsis:       [patch] pkg_delete(1) segfaults on '@pkgdep ' in +CONTENTS file
>Confidential:   no
>Severity:       serious
>Priority:       low
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sat Oct 10 04:50:06 UTC 2009
>Closed-Date:    Sat Oct 10 10:08:13 UTC 2009
>Last-Modified:  Sat Oct 10 10:08:13 UTC 2009
>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:

From: Mikolaj Golub <to.my.trociny@gmail.com>
To: TerryP <BigBoss1964@gmail.com>
Cc: bug-followup@FreeBSD.org
Subject: Re: bin/139470: pkg_delete segfaults on '@pkgdep ' in +CONTENTS file
Date: Sat, 10 Oct 2009 11:35:17 +0300

 This problem has already been reported several times (bin/135159, bin/133455,
 bin/138017).
 
 -- 
 Mikolaj Golub
State-Changed-From-To: open->closed 
State-Changed-By: remko 
State-Changed-When: Sat Oct 10 10:08:12 UTC 2009 
State-Changed-Why:  
Duplicate of 135159 133455 138017... Thanks for reporting though! 

http://www.freebsd.org/cgi/query-pr.cgi?pr=139470 
>Unformatted:
