(root)/
glibc-2.38/
grp/
tst-putgrent.c
       1  /* Test for processing of invalid group entries.  [BZ #18724]
       2     Copyright (C) 2015-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <errno.h>
      20  #include <grp.h>
      21  #include <stdbool.h>
      22  #include <stdio.h>
      23  #include <stdlib.h>
      24  #include <string.h>
      25  
      26  static bool errors;
      27  
      28  static void
      29  check (struct group e, const char *expected)
      30  {
      31    char *buf;
      32    size_t buf_size;
      33    FILE *f = open_memstream (&buf, &buf_size);
      34  
      35    if (f == NULL)
      36      {
      37        printf ("open_memstream: %m\n");
      38        errors = true;
      39        return;
      40      }
      41  
      42    int ret = putgrent (&e, f);
      43  
      44    if (expected == NULL)
      45      {
      46        if (ret == -1)
      47  	{
      48  	  if (errno != EINVAL)
      49  	    {
      50  	      printf ("putgrent: unexpected error code: %m\n");
      51  	      errors = true;
      52  	    }
      53  	}
      54        else
      55  	{
      56  	  printf ("putgrent: unexpected success (\"%s\", \"%s\")\n",
      57  		  e.gr_name, e.gr_passwd);
      58  	  errors = true;
      59  	}
      60      }
      61    else
      62      {
      63        /* Expect success.  */
      64        size_t expected_length = strlen (expected);
      65        if (ret == 0)
      66  	{
      67  	  long written = ftell (f);
      68  
      69  	  if (written <= 0 || fflush (f) < 0)
      70  	    {
      71  	      printf ("stream error: %m\n");
      72  	      errors = true;
      73  	    }
      74  	  else if (buf[written - 1] != '\n')
      75  	    {
      76  	      printf ("FAILED: \"%s\" without newline\n", expected);
      77  	      errors = true;
      78  	    }
      79  	  else if (strncmp (buf, expected, written - 1) != 0
      80  		   || written - 1 != expected_length)
      81  	    {
      82  	      buf[written - 1] = '\0';
      83  	      printf ("FAILED: \"%s\" (%ld), expected \"%s\" (%zu)\n",
      84  		      buf, written - 1, expected, expected_length);
      85  	      errors = true;
      86  	    }
      87  	}
      88        else
      89  	{
      90  	  printf ("FAILED: putgrent (expected \"%s\"): %m\n", expected);
      91  	  errors = true;
      92  	}
      93      }
      94  
      95    fclose (f);
      96    free (buf);
      97  }
      98  
      99  static int
     100  do_test (void)
     101  {
     102    check ((struct group) {
     103        .gr_name = (char *) "root",
     104      },
     105      "root::0:");
     106    check ((struct group) {
     107        .gr_name = (char *) "root",
     108        .gr_passwd = (char *) "password",
     109        .gr_gid = 1234,
     110        .gr_mem = (char *[2]) {(char *) "member1", NULL}
     111      },
     112      "root:password:1234:member1");
     113    check ((struct group) {
     114        .gr_name = (char *) "root",
     115        .gr_passwd = (char *) "password",
     116        .gr_gid = 1234,
     117        .gr_mem = (char *[3]) {(char *) "member1", (char *) "member2", NULL}
     118      },
     119      "root:password:1234:member1,member2");
     120  
     121    /* Bad values.  */
     122    {
     123      static const char *const bad_strings[] = {
     124        ":",
     125        "\n",
     126        ":bad",
     127        "\nbad",
     128        "b:ad",
     129        "b\nad",
     130        "bad:",
     131        "bad\n",
     132        "b:a\nd"
     133        ",",
     134        "\n,",
     135        ":,",
     136        ",bad",
     137        "b,ad",
     138        "bad,",
     139        NULL
     140      };
     141      for (const char *const *bad = bad_strings; *bad != NULL; ++bad)
     142        {
     143  	char *members[]
     144  	  = {(char *) "first", (char *) *bad, (char *) "last", NULL};
     145  	if (strpbrk (*bad, ":\n") != NULL)
     146  	  {
     147  	    check ((struct group) {
     148  		.gr_name = (char *) *bad,
     149  	      }, NULL);
     150  	    check ((struct group) {
     151  		.gr_name = (char *) "root",
     152  		.gr_passwd = (char *) *bad,
     153  	      }, NULL);
     154  	  }
     155  	check ((struct group) {
     156  	    .gr_name = (char *) "root",
     157  	    .gr_passwd = (char *) "password",
     158  	    .gr_mem = members,
     159  	  }, NULL);
     160        }
     161    }
     162  
     163    return errors;
     164  }
     165  
     166  #define TEST_FUNCTION do_test ()
     167  #include "../test-skeleton.c"