This is the mail archive of the libc-alpha@sources.redhat.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Possible bug in wcsxfrm() with included testcase


On Tue, Jul 22, 2003 at 03:43:36PM +0200, Jakub Jelinek wrote:
> On Tue, Jul 22, 2003 at 08:29:54AM -0500, Art Haas wrote:
> > /* this function comes from glibc info pages */
> > wchar_t *
> > mbstouwcs (const char *s)
> > {
> >   size_t len;
> >   wchar_t *result;
> >   wchar_t *wcp;
> >   wchar_t tmp[1];
> >   mbstate_t state;
> >   size_t nbytes;
> >   
> >   len = strlen(s);
> >   result = malloc((len + 1) * sizeof(wchar_t));
> >   if (result == NULL) {
> >     return NULL;
> >   }
> >   wcp = result;
> >   memset (&state, '\0', sizeof (state));
> >   while ((nbytes = mbrtowc (tmp, s, len, &state)) > 0)
> >     {
> >       if (nbytes >= (size_t) -2)
> > 	/* Invalid input string.  */
> > 	return NULL;
> >       *result++ = towupper (tmp[0]);
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> >       len -= nbytes;
> >       s += nbytes;
> >     }
> >   return result;
> ^^^^^^^^^^^^^^^^^^
> > }
> ...
> >       wcstr = mbstouwcs(cp);
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> >       wcsxfrm(result_wc, wcstr, xfrm_len + 1); /* BOOM! */
> >       free(result_wc);
> >       free(wcstr);
> ^^^^^^^^^^^^^^^^^^^^^^^
> 
> This doesn't look like a valid testcase.  mbstouwcs returns the end of
> the string, not the beginning (ie. what has been malloc'ed) and then you
> free the pointer returned by it (ie. end, not start of the memory block).
> 

You are right. The mbstouwcs() function should return wcp, not result.
The example came from the glibc info pages so the charset.texi page
needs to be fixed. I'll send a patch for that in another mail.

I've corrected the bug by returning wcp, and removed the towupper() as
that was pointless for this testcase. Valgrind isn't working on my
machine so I can't use it.

I've run the amended testcase again and still see the crash. Would you
try it again?

Art Haas

====================================================
/* test case attempt for wcsxfrm() */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <wchar.h>
// #include <wctype.h>
#include <dirent.h>
#include <locale.h>

/* this function comes from glibc info pages */
wchar_t *
mbstouwcs (const char *s)
{
  size_t len;
  wchar_t *result;
  wchar_t *wcp;
  wchar_t tmp[1];
  mbstate_t state;
  size_t nbytes;
  
  len = strlen(s);
  result = malloc((len + 1) * sizeof(wchar_t));
  if (result == NULL) {
    return NULL;
  }
  wcp = result;
  memset (&state, '\0', sizeof (state));
  while ((nbytes = mbrtowc (tmp, s, len, &state)) > 0)
    {
      if (nbytes >= (size_t) -2)
	/* Invalid input string.  */
	return NULL;
      *result++ = tmp[0];
      len -= nbytes;
      s += nbytes;
    }
  return wcp;
}

int
main(int argc, char ** argv) {
  DIR * dir;
  struct dirent * dentry;
  size_t namelen;
  size_t xfrm_len;
  char * cp = NULL;
  wchar_t * wcstr = NULL;
  wchar_t * result_wc = NULL;

  if (argc < 2) {
    printf("Pass a directory name!\n");
    return EXIT_FAILURE;
  }
  dir = opendir(argv[1]);
  if (dir == NULL) {
    printf("opendir() failed on '%s'\n", argv[1]);
    return EXIT_FAILURE;
  }
  setlocale (LC_COLLATE, "");
  while ((dentry = readdir(dir)) != NULL)
    {
      printf("entry name: '%s'\n", dentry->d_name);
      namelen = strlen(dentry->d_name);
      cp = malloc(namelen + 1);
      if (cp == NULL) {
	printf("malloc() failure\n");
	closedir(dir);
	return EXIT_FAILURE;
      }
      strcpy(cp, dentry->d_name);
      wcstr = mbstouwcs(cp);
      if (wcstr == NULL) {
	printf("mbstouwcs() failure\n");
	free(cp);
	closedir(dir);
	return EXIT_FAILURE;
      }
      xfrm_len = wcsxfrm(NULL, wcstr, 0);
      printf("xfrm_len: %zd\n", xfrm_len);
      result_wc = malloc((xfrm_len + 1) * sizeof(wchar_t));
      if (result_wc == NULL) {
	printf("malloc() failure\n");
	free(wcstr);
	free(cp);
	closedir(dir);
	return EXIT_FAILURE;
      }
      wcsxfrm(result_wc, wcstr, xfrm_len + 1); /* BOOM! */
      free(result_wc);
      free(wcstr);
      free(cp);
    }
  closedir(dir);
  return EXIT_SUCCESS;
}

-- 
Man once surrendering his reason, has no remaining guard against absurdities
the most monstrous, and like a ship without rudder, is the sport of every wind.

-Thomas Jefferson to James Smith, 1822


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]