View | Details | Raw Unified | Return to bug 195128 | Differences between
and this patch

Collapse All | Expand All

(-)src/lib/libc/gen/getcap.c (+22 lines)
Lines 32-51 Link Here
32
32
33
#if defined(LIBC_SCCS) && !defined(lint)
33
#if defined(LIBC_SCCS) && !defined(lint)
34
static char sccsid[] = "@(#)getcap.c	8.3 (Berkeley) 3/25/94";
34
static char sccsid[] = "@(#)getcap.c	8.3 (Berkeley) 3/25/94";
35
#endif /* LIBC_SCCS and not lint */
35
#endif /* LIBC_SCCS and not lint */
36
#include <sys/cdefs.h>
36
#include <sys/cdefs.h>
37
__FBSDID("$FreeBSD$");
37
__FBSDID("$FreeBSD$");
38
38
39
#include "namespace.h"
39
#include "namespace.h"
40
#include <sys/types.h>
40
#include <sys/types.h>
41
41
42
#include <assert.h>
42
#include <ctype.h>
43
#include <ctype.h>
43
#include <errno.h>
44
#include <errno.h>
44
#include <fcntl.h>
45
#include <fcntl.h>
45
#include <limits.h>
46
#include <limits.h>
46
#include <stdio.h>
47
#include <stdio.h>
47
#include <stdlib.h>
48
#include <stdlib.h>
48
#include <string.h>
49
#include <string.h>
49
#include <unistd.h>
50
#include <unistd.h>
50
#include "un-namespace.h"
51
#include "un-namespace.h"
51
52
Lines 57-81 __FBSDID("$FreeBSD$"); Link Here
57
#define	MAX_RECURSION	32		/* maximum getent recursion */
58
#define	MAX_RECURSION	32		/* maximum getent recursion */
58
#define	SFRAG		100		/* cgetstr mallocs in SFRAG chunks */
59
#define	SFRAG		100		/* cgetstr mallocs in SFRAG chunks */
59
60
60
#define RECOK	(char)0
61
#define RECOK	(char)0
61
#define TCERR	(char)1
62
#define TCERR	(char)1
62
#define	SHADOW	(char)2
63
#define	SHADOW	(char)2
63
64
64
static size_t	 topreclen;	/* toprec length */
65
static size_t	 topreclen;	/* toprec length */
65
static char	*toprec;	/* Additional record specified by cgetset() */
66
static char	*toprec;	/* Additional record specified by cgetset() */
66
static int	 gottoprec;	/* Flag indicating retrieval of toprecord */
67
static int	 gottoprec;	/* Flag indicating retrieval of toprecord */
68
static void	**allocs;	/* Array of allocations to free in cgetclose */
69
static int	nallocs;	/* Number of allocs */
67
70
68
static int	cdbget(DB *, char **, const char *);
71
static int	cdbget(DB *, char **, const char *);
69
static int 	getent(char **, u_int *, char **, int, const char *, int, char *);
72
static int 	getent(char **, u_int *, char **, int, const char *, int, char *);
70
static int	nfcmp(char *, char *);
73
static int	nfcmp(char *, char *);
71
74
75
static void
76
cgetregisteralloc(void *alloc)
77
{
78
	nallocs++;
79
	allocs = realloc(allocs, nallocs * sizeof(allocs[0]));
80
	assert(allocs != NULL);
81
	allocs[nallocs - 1] = alloc;
82
}
83
72
/*
84
/*
73
 * Cgetset() allows the addition of a user specified buffer to be added
85
 * Cgetset() allows the addition of a user specified buffer to be added
74
 * to the database array, in effect "pushing" the buffer on top of the
86
 * to the database array, in effect "pushing" the buffer on top of the
75
 * virtual database. 0 is returned on success, -1 on failure.
87
 * virtual database. 0 is returned on success, -1 on failure.
76
 */
88
 */
77
int
89
int
78
cgetset(const char *ent)
90
cgetset(const char *ent)
79
{
91
{
80
	if (ent == NULL) {
92
	if (ent == NULL) {
81
		if (toprec)
93
		if (toprec)
Lines 517-536 tc_exp: { Link Here
517
	if (myfd)
529
	if (myfd)
518
		(void)_close(fd);
530
		(void)_close(fd);
519
	*len = rp - record - 1;	/* don't count NUL */
531
	*len = rp - record - 1;	/* don't count NUL */
520
	if (r_end > rp)
532
	if (r_end > rp)
521
		if ((record =
533
		if ((record =
522
		     reallocf(record, (size_t)(rp - record))) == NULL) {
534
		     reallocf(record, (size_t)(rp - record))) == NULL) {
523
			errno = ENOMEM;
535
			errno = ENOMEM;
524
			return (-2);
536
			return (-2);
525
		}
537
		}
526
538
539
	cgetregisteralloc(record);
527
	*cap = record;
540
	*cap = record;
528
	if (tc_not_resolved)
541
	if (tc_not_resolved)
529
		return (1);
542
		return (1);
530
	return (0);
543
	return (0);
531
}
544
}
532
545
533
static int
546
static int
534
cdbget(DB *capdbp, char **bp, const char *name)
547
cdbget(DB *capdbp, char **bp, const char *name)
535
{
548
{
536
	DBT key, data;
549
	DBT key, data;
Lines 627-646 static char **dbp; Link Here
627
640
628
int
641
int
629
cgetclose(void)
642
cgetclose(void)
630
{
643
{
631
	if (pfp != NULL) {
644
	if (pfp != NULL) {
632
		(void)fclose(pfp);
645
		(void)fclose(pfp);
633
		pfp = NULL;
646
		pfp = NULL;
634
	}
647
	}
635
	dbp = NULL;
648
	dbp = NULL;
636
	gottoprec = 0;
649
	gottoprec = 0;
650
	free(toprec);
651
 	if (allocs != NULL) {
652
		while (nallocs-- > 0)
653
			free(allocs[nallocs - 1]);
654
		free(allocs);
655
		allocs = NULL;
656
	}
637
	slash = 0;
657
	slash = 0;
638
	return(0);
658
	return(0);
639
}
659
}
640
660
641
/*
661
/*
642
 * Cgetnext() gets either the first or next entry in the logical database
662
 * Cgetnext() gets either the first or next entry in the logical database
643
 * specified by db_array.  It returns 0 upon completion of the database, 1
663
 * specified by db_array.  It returns 0 upon completion of the database, 1
644
 * upon returning an entry with more remaining, and -1 if an error occurs.
664
 * upon returning an entry with more remaining, and -1 if an error occurs.
645
 */
665
 */
646
int
666
int
Lines 886-905 cgetstr(char *buf, const char *cap, char Link Here
886
	*mp++ = '\0';	/* loop invariant let's us do this */
906
	*mp++ = '\0';	/* loop invariant let's us do this */
887
	m_room--;
907
	m_room--;
888
	len = mp - mem - 1;
908
	len = mp - mem - 1;
889
909
890
	/*
910
	/*
891
	 * Give back any extra memory and return value and success.
911
	 * Give back any extra memory and return value and success.
892
	 */
912
	 */
893
	if (m_room != 0)
913
	if (m_room != 0)
894
		if ((mem = reallocf(mem, (size_t)(mp - mem))) == NULL)
914
		if ((mem = reallocf(mem, (size_t)(mp - mem))) == NULL)
895
			return (-2);
915
			return (-2);
916
	cgetregisteralloc(mem);
896
	*str = mem;
917
	*str = mem;
897
	return (len);
918
	return (len);
898
}
919
}
899
920
900
/*
921
/*
901
 * Cgetustr retrieves the value of the string capability cap from the
922
 * Cgetustr retrieves the value of the string capability cap from the
902
 * capability record pointed to by buf.  The difference between cgetustr()
923
 * capability record pointed to by buf.  The difference between cgetustr()
903
 * and cgetstr() is that cgetustr does not decode escapes but rather treats
924
 * and cgetstr() is that cgetustr does not decode escapes but rather treats
904
 * all characters literally.  A pointer to a  NUL terminated malloc'd
925
 * all characters literally.  A pointer to a  NUL terminated malloc'd
905
 * copy of the string is returned in the char pointed to by str.  The
926
 * copy of the string is returned in the char pointed to by str.  The
Lines 958-977 cgetustr(char *buf, const char *cap, cha Link Here
958
	*mp++ = '\0';	/* loop invariant let's us do this */
979
	*mp++ = '\0';	/* loop invariant let's us do this */
959
	m_room--;
980
	m_room--;
960
	len = mp - mem - 1;
981
	len = mp - mem - 1;
961
982
962
	/*
983
	/*
963
	 * Give back any extra memory and return value and success.
984
	 * Give back any extra memory and return value and success.
964
	 */
985
	 */
965
	if (m_room != 0)
986
	if (m_room != 0)
966
		if ((mem = reallocf(mem, (size_t)(mp - mem))) == NULL)
987
		if ((mem = reallocf(mem, (size_t)(mp - mem))) == NULL)
967
			return (-2);
988
			return (-2);
989
	cgetregisteralloc(mem);
968
	*str = mem;
990
	*str = mem;
969
	return (len);
991
	return (len);
970
}
992
}
971
993
972
/*
994
/*
973
 * Cgetnum retrieves the value of the numeric capability cap from the
995
 * Cgetnum retrieves the value of the numeric capability cap from the
974
 * capability record pointed to by buf.  The numeric value is returned in
996
 * capability record pointed to by buf.  The numeric value is returned in
975
 * the long pointed to by num.  0 is returned on success, -1 if the requested
997
 * the long pointed to by num.  0 is returned on success, -1 if the requested
976
 * numeric capability couldn't be found.
998
 * numeric capability couldn't be found.
977
 */
999
 */
(-)src/lib/libc/tests/gen/Makefile (+1 lines)
Lines 5-24 Link Here
5
CFLAGS+=	-I${.CURDIR:H}
5
CFLAGS+=	-I${.CURDIR:H}
6
6
7
TESTSDIR=	${TESTSBASE}/lib/libc/gen
7
TESTSDIR=	${TESTSBASE}/lib/libc/gen
8
8
9
#ATF_TESTS+=	posix_spawn
9
#ATF_TESTS+=	posix_spawn
10
TESTS_SUBDIRS=	posix_spawn
10
TESTS_SUBDIRS=	posix_spawn
11
11
12
ATF_TESTS_C=	t_alarm
12
ATF_TESTS_C=	t_alarm
13
ATF_TESTS_C+=	t_assert
13
ATF_TESTS_C+=	t_assert
14
ATF_TESTS_C+=	t_basedirname
14
ATF_TESTS_C+=	t_basedirname
15
ATF_TESTS_C+=	t_getcap
15
# XXX: F_MAXFD DNE
16
# XXX: F_MAXFD DNE
16
#TESTS_C+=	t_closefrom
17
#TESTS_C+=	t_closefrom
17
# XXX: missing cpuset* support.
18
# XXX: missing cpuset* support.
18
#TESTS_C+=	t_cpuset
19
#TESTS_C+=	t_cpuset
19
ATF_TESTS_C+=	t_dir
20
ATF_TESTS_C+=	t_dir
20
ATF_TESTS_C+=	t_fmtcheck
21
ATF_TESTS_C+=	t_fmtcheck
21
ATF_TESTS_C+=	t_fnmatch
22
ATF_TESTS_C+=	t_fnmatch
22
ATF_TESTS_C+=	t_fpclassify
23
ATF_TESTS_C+=	t_fpclassify
23
ATF_TESTS_C+=	t_fpsetmask
24
ATF_TESTS_C+=	t_fpsetmask
24
ATF_TESTS_C+=	t_fpsetround
25
ATF_TESTS_C+=	t_fpsetround
(-)src/lib/libc/tests/gen/t_getcap.c (+116 lines)
Line 0 Link Here
1
/*-
2
 * Copyright (c) 2014 EMC / Isilon Storage Division
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 * 1. Redistributions of source code must retain the above copyright
9
 *    notice, this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright
11
 *    notice, this list of conditions and the following disclaimer in the
12
 *    documentation and/or other materials provided with the distribution.
13
 *
14
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
15
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
16
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
18
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24
 * POSSIBILITY OF SUCH DAMAGE.
25
 */
26
27
#include <atf-c.h>
28
29
#include <assert.h>
30
#include <dirent.h>
31
#include <err.h>
32
#include <fcntl.h>
33
#include <malloc_np.h>
34
#include <stdio.h>
35
#include <stdint.h>
36
#include <stdlib.h>
37
#include <string.h>
38
#include <unistd.h>
39
40
ATF_TC(cgetstr_leak);
41
ATF_TC_HEAD(cgetstr_leak, tc)
42
{
43
44
	atf_tc_set_md_var(tc, "descr",
45
	    "Check cgetstr(3) for memory leakage (Bug 195128)");
46
}
47
48
void
49
malgetuint64(char *name, uint64_t *val) {
50
	size_t len;
51
52
	len = sizeof(*val);
53
        if (mallctl(name, val, &len, NULL, 0) == -1)
54
                err(2, "mallctl failed");
55
	if (len != sizeof(*val))
56
		err(2, "bad size from mallctl");
57
}
58
59
int64_t
60
malallocated(void) {
61
	uint64_t allocated, deallocated;
62
63
	malgetuint64("thread.allocated", &allocated);
64
	malgetuint64("thread.deallocated", &deallocated);
65
	printf("alloc: %jd dealloc: %jd delta: %jd\n", (uintmax_t)allocated, (uintmax_t)deallocated, (uintmax_t)(allocated - deallocated));
66
	return ((int64_t)(allocated - deallocated));
67
}
68
69
ATF_TC_BODY(cgetstr_leak, tc)
70
{
71
	char *buf, *str, *dbarray[] = { "/etc/login.conf" };
72
	int errcode, i;
73
	int64_t allocated, start;
74
75
	buf = "opt.dss";
76
	str = "primary";
77
	i = 1;
78
        if (mallctl(buf, NULL, 0, str, strlen(str) + 1) == -1)
79
                err(2, "mallctl failed");
80
81
	start = malallocated();
82
	printf("Start %jd\n", (uintmax_t)start);
83
84
	i = cgetent(&buf, dbarray, "default");
85
	if (i == -1)
86
		atf_tc_skip("Unable to find default class in login.conf");
87
	if (i == -2)
88
		atf_tc_skip("Error reading login.conf");
89
90
	allocated = malallocated();
91
	printf("cgetent %jd\n", (uintmax_t)allocated);
92
	for (i = 0; i < 1000; i++) {
93
		if ((errcode = cgetstr(buf, "path", &str)) < 0)
94
			atf_tc_skip("cgetstr failed with %d", errcode);
95
	}
96
	allocated = malallocated();
97
	printf("cgetstr %jd\n", (uintmax_t)allocated);
98
	free(buf);
99
	cgetclose();
100
101
	allocated = malallocated();
102
	printf("end %jd\n", (uintmax_t)allocated);
103
	if (allocated - start > 4096) {
104
		atf_tc_fail("Failure: leaked %jd bytes", allocated - start);
105
	} else {
106
		(void)printf("OK: used %jd bytes\n", allocated - start);
107
	}
108
}
109
110
ATF_TP_ADD_TCS(tp)
111
{
112
113
	ATF_TP_ADD_TC(tp, cgetstr_leak);
114
115
	return atf_no_error();
116
}

Return to bug 195128