NetBSD Problem Report #45288

From www@NetBSD.org  Wed Aug 24 09:12:56 2011
Return-Path: <www@NetBSD.org>
Received: from mail.netbsd.org (mail.netbsd.org [204.152.190.11])
	by www.NetBSD.org (Postfix) with ESMTP id 1BF0763BED9
	for <gnats-bugs@gnats.NetBSD.org>; Wed, 24 Aug 2011 09:12:56 +0000 (UTC)
Message-Id: <20110824091254.DF15763BAC3@www.NetBSD.org>
Date: Wed, 24 Aug 2011 09:12:54 +0000 (UTC)
From: jackjost@users.sourceforge.net
Reply-To: jackjost@users.sourceforge.net
To: gnats-bugs@NetBSD.org
Subject: tsearch()/tfind()/tdelete() shall accept key=NULL 
X-Send-Pr-Version: www-1.0

>Number:         45288
>Category:       lib
>Synopsis:       tsearch()/tfind()/tdelete() shall accept key=NULL
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    lib-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Wed Aug 24 09:15:00 +0000 2011
>Originator:     Jack Jost
>Release:        mingw's libc derived from BSD
>Organization:
>Environment:
all BSD libc and derived sources (mingw etc.)
>Description:
/* this code exposes 2 POSIX-incompatibilities in search.h/tfind/delete:
  - compilation causes a NULL-warning, although key=NULL is allowed ("warning: null argument where non-null required (argument 1) [-Wnonnull]")
  - the second deletion method using tdelete() only causes this assertion at runtime:
      Assertion failed! File: ../../../build/mingw/mingw-w64-crt/misc/tdelete.c, Line 33
      Expression: vkey != NULL. abnormal program termination

Test case follows, expected output below source:
 */


#include <stdio.h>
#include <string.h>
#include <search.h>

static int node_cmp (const void *a, const void *b)
{
	return strcmp((const char *) a, (const char *) b);
}

/* match any node... */
static int node_any (const void *a, const void *b)
{
	return 0;
}

void print_node (const void *ptr, VISIT order, int level)
{
	const char *s = *(const char **) ptr;
	if (order == postorder || order == leaf)
		printf("%s\n", s);
}

int main (int argc, char **argv)
{
	void *root = NULL;
	tsearch("aaa", &root, node_cmp);
	tsearch("bbb", &root, node_cmp);
	tsearch("ccc", &root, node_cmp);
	printf("---------- tree after insertion of 3 nodes:\n");
	twalk(root, print_node);
	printf("----------\n");
	void *nodep;
	while ((nodep = tfind(NULL, &root, node_any))) {
		const char *key = * (const char **) nodep;
		tdelete(key, &root, node_cmp);
	}
	printf("---------- tree after deletion of all nodes using tfind()+tdelete():\n");
	twalk(root, print_node);
	printf("----------\n");
	tsearch("ddd", &root, node_cmp);
	tsearch("eee", &root, node_cmp);
	tsearch("fff", &root, node_cmp);
	printf("---------- tree after insertion of 3 new nodes:\n");
	twalk(root, print_node);
	printf("----------\n");
	while (tdelete(NULL, &root, node_any) != NULL)
		;
	printf("---------- tree after deletion of all nodes using tdelete() only:\n");
	twalk(root, print_node);
	printf("----------\n");
	return 0;
}


/* ------------ requested output:
$ valgrind ./search_test
==9853== Memcheck, a memory error detector
==9853== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==9853== Using Valgrind-3.7.0.SVN and LibVEX; rerun with -h for copyright info
==9853== Command: ./search_test
==9853== 
---------- tree after insertion of 3 nodes:
aaa
bbb
ccc
----------
---------- tree after deletion of all nodes using tfind()+tdelete():
----------
---------- tree after insertion of 3 new nodes:
ddd
eee
fff
----------
---------- tree after deletion of all nodes using tdelete() only:
----------
==9853== 
==9853== HEAP SUMMARY:
==9853==     in use at exit: 0 bytes in 0 blocks
==9853==   total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==9853== 
==9853== All heap blocks were freed -- no leaks are possible
==9853== 
==9853== For counts of detected and suppressed errors, rerun with: -v
==9853== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
*/
>How-To-Repeat:

>Fix:
key=NULL is explicitly not forbidden by POSIX and makes sense for match-any-node-tree destructors. However, vrootp is not checked for NULL. Solution: Replace _DIAGASSERT(vkey != NULL) by _DIAGASSERT(vrootp != NULL).

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.39 2013/11/01 18:47:49 spz Exp $
$NetBSD: gnats_config.sh,v 1.8 2006/05/07 09:23:38 tsutsui Exp $
Copyright © 1994-2007 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.