License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
+#include <assert.h>
#include <nss.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <array_length.h>
+/* For NSS_BUFLEN_GROUP define. */
+#include "nss/grp.h"
+#include <support/test-driver.h>
#include <support/support.h>
#include "nss_test.h"
"foo", "bar", NULL
};
-static const char *group_2[] = {
- "foo", "dick", "harry", NULL
-};
+/* Enough entries to exceed NSS_BUFLEN_GROUP and trigger ERANGE. */
+static char *group_2[256];
-/* Note that deduplication is NOT supposed to happen. */
-static const char *merge_1[] = {
- "foo", "bar", "foo", "dick", "harry", NULL
-};
+static char *merge_1[array_length(group_1) + array_length (group_2) - 1];
static const char *group_4[] = {
"fred", "wilma", NULL
GRP_LAST ()
};
+/* In order to trigger ERANGE checking the minimum size of
+ group_table_data2 should exceed NSS_BUFLEN_GROUP which is used
+ internally by getgrgid. We use 8 bytes per group_2 string as
+ a lower bound. */
+_Static_assert (sizeof (group_table_data2) + array_length (group_2) * 8
+ >= NSS_BUFLEN_GROUP,
+ "test group table size should exceed NSS_BUFLEN_GROUP");
+
/* This is the data we compare against. */
static struct group group_table[] = {
GRP_N(1, "name1", merge_1),
do_test (void)
{
int retval = 0;
- int i;
+ int i, member_cnt;
struct group *g = NULL;
uintptr_t align_mask;
+ uintptr_t align_mem_mask;
- __nss_configure_lookup ("group", "test1 [SUCCESS=merge] test2");
+ /* At least 3 service modules are needed to reproduce BZ#33361. */
+ __nss_configure_lookup ("group", "test1 [SUCCESS=merge] test2 files");
- align_mask = __alignof__ (struct group *) - 1;
+ /* Test increasing sizes of group_2 to see if we fail, starting with
+ member_cnt == 1 to ensure we always check for no de-duplication
+ e.g. { "foo", NULL } */
+ for (member_cnt = 1; member_cnt < array_length (group_2); member_cnt++)
+ {
+ verbose_printf ("Outer loop - member_cnt is %d\n", member_cnt);
- setgrent ();
+ /* Initialize group_2 */
+ for (i = 0; i < member_cnt; i++)
+ {
+ /* Note that deduplication is NOT supposed to happen. */
+ if (i == 0)
+ group_2[i] = xstrdup ("foo");
+ else
+ group_2[i] = xasprintf ("foobar%d", i);
+ }
+ group_2[member_cnt] = NULL;
- for (i = 0; group_table[i].gr_gid; ++i)
- {
- g = getgrgid (group_table[i].gr_gid);
- if (g)
+ /* Create the merged list to verify against */
+
+ /* Copy group_1 to the merge list (excluding NULL) */
+ for (i = 0; i < array_length (group_1) - 1; i++)
+ {
+ merge_1[i] = xasprintf ("%s", group_1[i]);
+ verbose_printf ("MERGED LIST of [%d] is %s\n", i, merge_1[i]);
+ }
+
+ /* Add group_2 to the merge list */
+ int group2_index = 0;
+ for (i = array_length (group_1) - 1;
+ i < array_length (group_1) - 1 + member_cnt; i++)
{
- retval += compare_groups (i, g, & group_table[i]);
- if ((uintptr_t)g & align_mask)
+ merge_1[i] = xasprintf ("%s", group_2[group2_index++]);
+ verbose_printf ("MERGED LIST of [%d] is %s\n", i, merge_1[i]);
+ }
+ merge_1[array_length(group_1) - 1 + member_cnt]= NULL;
+
+ align_mask = __alignof__ (struct group) - 1;
+ align_mem_mask = __alignof__ (char *) - 1;
+
+ setgrent ();
+
+ for (i = 0; group_table[i].gr_gid; ++i)
+ {
+ g = getgrgid (group_table[i].gr_gid);
+ if (g)
{
- printf("FAIL: [%d] unaligned group %p\n", i, g);
- ++retval;
+ retval += compare_groups (i, g, & group_table[i]);
+ if ((uintptr_t)g & align_mask)
+ {
+ printf ("FAIL: [%d] unaligned group %p\n", i, g);
+ ++retval;
+ }
+ if ((uintptr_t)(g->gr_mem) & align_mem_mask)
+ {
+ printf ("FAIL: [%d] unaligned member list %p\n",
+ i, g->gr_mem);
+ ++retval;
+ }
}
- if ((uintptr_t)(g->gr_mem) & align_mask)
+ else
{
- printf("FAIL: [%d] unaligned member list %p\n", i, g->gr_mem);
+ printf ("FAIL: [%d] group %u.%s not found\n", i,
+ group_table[i].gr_gid, group_table[i].gr_name);
++retval;
}
}
- else
- {
- printf ("FAIL: [%d] group %u.%s not found\n", i,
- group_table[i].gr_gid, group_table[i].gr_name);
- ++retval;
- }
- }
- endgrent ();
+ endgrent ();
+
+ /* Free malloc'd array members (including the NULL) */
+ for (i = 0; i < member_cnt; i++)
+ free (group_2[i]);
+ for (i = 0; i < array_length (group_1) + member_cnt; i++)
+ free (merge_1[i]);
+ }
#define EXPECTED 0
if (retval == EXPECTED)