public inbox for libc-hacker@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] Fix snprintf
@ 2003-05-26 16:41 Jakub Jelinek
  2003-05-27  7:40 ` Ulrich Drepper
  0 siblings, 1 reply; 2+ messages in thread
From: Jakub Jelinek @ 2003-05-26 16:41 UTC (permalink / raw)
  To: Ulrich Drepper, Roland McGrath; +Cc: Glibc hackers

Hi!

ATM sprintf creates at most 64M string, furthermore although snprintf
is given size_t for max length, it is casted to int and thus it might be
much smaller limit than the one given by the user (consider e.g.
sprintf (buf, 0x100000010, fmt, args)).

2003-05-26  Jakub Jelinek  <jakub@redhat.com>

	* libio/strops.c (_IO_str_init_static): Change into a wrapper around
	_IO_str_init_static_internal.
	(_IO_str_init_static_internal): Moved from _IO_str_init_static,
	change size argument to _IO_size_t, don't limit sprintf to 64M.
	(_IO_str_init_readonly): Call _IO_str_init_static_internal.
	* libio/wstrops.c (_IO_wstr_init_static): Change size argument to
	_IO_size_t, don't limit swprintf to 256M.
	(_IO_wstr_init_readonly): Remove.
	* libio/libioP.h (_IO_str_init_static_internal, _IO_wstr_init_static):
	Adjust prototypes.
	(_IO_wstr_init_readonly): Remove prototype.
	* libio/iovsprintf.c (_IO_vsprintf): Use
	_IO_str_init_static_internal instead of INTUSE(_IO_str_init_static).
	* libio/iovsscanf.c (_IO_vsscanf): Likewise.
	* libio/memstream.c (open_memstream): Likewise.
	* libio/obprintf.c (_IO_obstack_vfprintf): Likewise.
	* libio/vasprintf.c (_IO_vasprintf): Likewise.
	* libio/vsnprintf.c (_IO_vsnprintf): Likewise.
	* stdio-common/tst-sprintf.c (main): Add new test.

--- libc/libio/strops.c.jj	2002-02-28 06:31:50.000000000 -0500
+++ libc/libio/strops.c	2003-05-26 08:34:39.000000000 -0400
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1997-2000, 2001, 2002 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 1997-2003 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -63,33 +63,22 @@
 #endif
 
 void
-_IO_str_init_static (sf, ptr, size, pstart)
+_IO_str_init_static_internal (sf, ptr, size, pstart)
      _IO_strfile *sf;
      char *ptr;
-     int size;
+     _IO_size_t size;
      char *pstart;
 {
   _IO_FILE *fp = &sf->_sbf._f;
+  char *end;
 
   if (size == 0)
-    size = strlen (ptr);
-  else if (size < 0)
-    {
-      /* If size is negative 'the characters are assumed to
-	 continue indefinitely.'  This is kind of messy ... */
-      int s;
-      size = 512;
-      /* Try increasing powers of 2, as long as we don't wrap around. */
-      for (; s = 2*size, s > 0 && ptr + s > ptr && s < 0x4000000L; )
-	size = s;
-      /* Try increasing size as much as we can without wrapping around. */
-      for (s = size >> 1; s > 0; s >>= 1)
-	{
-	  if (ptr + size + s > ptr)
-	    size += s;
-	}
-    }
-  INTUSE(_IO_setb) (fp, ptr, ptr + size, 0);
+    end = __rawmemchr (ptr, '\0');
+  else if ((_IO_size_t) ptr + size > (_IO_size_t) ptr)
+    end = ptr + size;
+  else
+    end = (char *) -1;
+  INTUSE(_IO_setb) (fp, ptr, end, 0);
 
   fp->_IO_write_base = ptr;
   fp->_IO_read_base = ptr;
@@ -97,19 +86,28 @@ _IO_str_init_static (sf, ptr, size, psta
   if (pstart)
     {
       fp->_IO_write_ptr = pstart;
-      fp->_IO_write_end = ptr + size;
+      fp->_IO_write_end = end;
       fp->_IO_read_end = pstart;
     }
   else
     {
       fp->_IO_write_ptr = ptr;
       fp->_IO_write_end = ptr;
-      fp->_IO_read_end = ptr+size;
+      fp->_IO_read_end = end;
     }
   /* A null _allocate_buffer function flags the strfile as being static. */
   sf->_s._allocate_buffer = (_IO_alloc_type) 0;
 }
-INTDEF(_IO_str_init_static)
+
+void
+_IO_str_init_static (sf, ptr, size, pstart)
+     _IO_strfile *sf;
+     char *ptr;
+     int size;
+     char *pstart;
+{
+  return _IO_str_init_static_internal (sf, ptr, size < 0 ? -1 : size, pstart);
+}
 
 void
 _IO_str_init_readonly (sf, ptr, size)
@@ -117,7 +115,7 @@ _IO_str_init_readonly (sf, ptr, size)
      const char *ptr;
      int size;
 {
-  INTUSE(_IO_str_init_static) (sf, (char *) ptr, size, NULL);
+  _IO_str_init_static_internal (sf, (char *) ptr, size < 0 ? -1 : size, NULL);
   sf->_sbf._f._IO_file_flags |= _IO_NO_WRITES;
 }
 
--- libc/libio/libioP.h.jj	2003-05-13 16:58:06.000000000 -0400
+++ libc/libio/libioP.h	2003-05-26 09:27:06.000000000 -0400
@@ -619,8 +619,7 @@ extern void _IO_str_init_readonly __P ((
 extern _IO_ssize_t _IO_str_count __P ((_IO_FILE *));
 
 /* And the wide character versions.  */
-extern void _IO_wstr_init_static __P ((_IO_FILE *, wchar_t *, int, wchar_t *));
-extern void _IO_wstr_init_readonly __P ((_IO_FILE *, const char *, int));
+extern void _IO_wstr_init_static __P ((_IO_FILE *, wchar_t *, _IO_size_t, wchar_t *));
 extern _IO_ssize_t _IO_wstr_count __P ((_IO_FILE *));
 extern _IO_wint_t _IO_wstr_overflow __P ((_IO_FILE *, _IO_wint_t));
 extern _IO_wint_t _IO_wstr_underflow __P ((_IO_FILE *));
@@ -710,7 +709,7 @@ extern int _IO_str_pbackfail_internal __
 extern _IO_off64_t _IO_str_seekoff_internal __P ((_IO_FILE *, _IO_off64_t,
 						  int, int));
 extern void _IO_str_init_static_internal __P ((struct _IO_strfile_ *, char *,
-					       int, char *));
+					       _IO_size_t, char *));
 
 extern struct _IO_jump_t _IO_file_jumps_internal attribute_hidden;
 extern struct _IO_jump_t _IO_wfile_jumps_internal attribute_hidden;
--- libc/libio/iovsprintf.c.jj	2002-02-28 06:31:50.000000000 -0500
+++ libc/libio/iovsprintf.c	2003-05-26 08:35:43.000000000 -0400
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1997-2000, 2001, 2002 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 1997-2003 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -42,7 +42,7 @@ _IO_vsprintf (string, format, args)
 #endif
   _IO_no_init (&sf._sbf._f, _IO_USER_LOCK, -1, NULL, NULL);
   _IO_JUMPS ((struct _IO_FILE_plus *) &sf._sbf) = &_IO_str_jumps;
-  INTUSE(_IO_str_init_static) (&sf, string, -1, string);
+  _IO_str_init_static_internal (&sf, string, -1, string);
   ret = INTUSE(_IO_vfprintf) ((_IO_FILE *) &sf._sbf, format, args);
   _IO_putc_unlocked ('\0', (_IO_FILE *) &sf._sbf);
   return ret;
--- libc/libio/iovsscanf.c.jj	2002-02-28 06:31:50.000000000 -0500
+++ libc/libio/iovsscanf.c	2003-05-26 08:36:27.000000000 -0400
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1997-2000, 2001, 2002 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 1997-2003 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -41,7 +41,7 @@ _IO_vsscanf (string, format, args)
 #endif
   _IO_no_init (&sf._sbf._f, _IO_USER_LOCK, -1, NULL, NULL);
   _IO_JUMPS ((struct _IO_FILE_plus *) &sf._sbf) = &_IO_str_jumps;
-  INTUSE(_IO_str_init_static) (&sf, (char*)string, 0, NULL);
+  _IO_str_init_static_internal (&sf, (char*)string, 0, NULL);
   ret = INTUSE(_IO_vfscanf) ((_IO_FILE *) &sf._sbf, format, args, NULL);
   return ret;
 }
--- libc/libio/memstream.c.jj	2002-08-12 09:27:47.000000000 -0400
+++ libc/libio/memstream.c	2003-05-26 08:37:45.000000000 -0400
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995,1996,1997,1999,2000,2002 Free Software Foundation, Inc.
+/* Copyright (C) 1995-1997,1999,2000,2002,2003 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -114,7 +114,7 @@ open_memstream (bufloc, sizeloc)
     return NULL;
   _IO_no_init (&new_f->fp._sf._sbf._f, 0, 0, &new_f->wd, &_IO_wmem_jumps);
   _IO_JUMPS ((struct _IO_FILE_plus *) &new_f->fp._sf._sbf) = &_IO_mem_jumps;
-  INTUSE(_IO_str_init_static) (&new_f->fp._sf, buf, _IO_BUFSIZ, buf);
+  _IO_str_init_static_internal (&new_f->fp._sf, buf, _IO_BUFSIZ, buf);
   new_f->fp._sf._sbf._f._flags &= ~_IO_USER_BUF;
   new_f->fp._sf._s._allocate_buffer = (_IO_alloc_type) malloc;
   new_f->fp._sf._s._free_buffer = (_IO_free_type) free;
--- libc/libio/obprintf.c.jj	2002-02-28 06:31:50.000000000 -0500
+++ libc/libio/obprintf.c	2003-05-26 08:38:56.000000000 -0400
@@ -1,5 +1,5 @@
 /* Print output of stream to given obstack.
-   Copyright (C) 1996,1997,1999,2000,2001,2002 Free Software Foundation, Inc.
+   Copyright (C) 1996,1997,1999-2003 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
 
@@ -153,9 +153,9 @@ _IO_obstack_vprintf (struct obstack *obs
       assert (size != 0);
     }
 
-  INTUSE(_IO_str_init_static) ((struct _IO_strfile_ *) &new_f.ofile,
-			       obstack_base (obstack),
-			       size, obstack_next_free (obstack));
+  _IO_str_init_static_internal ((struct _IO_strfile_ *) &new_f.ofile,
+				obstack_base (obstack),
+				size, obstack_next_free (obstack));
   /* Now allocate the rest of the current chunk.  */
   assert (size == (new_f.ofile.file.file._IO_write_end
 		   - new_f.ofile.file.file._IO_write_base));
--- libc/libio/vasprintf.c.jj	2002-02-28 06:31:50.000000000 -0500
+++ libc/libio/vasprintf.c	2003-05-26 08:39:54.000000000 -0400
@@ -54,7 +54,7 @@ _IO_vasprintf (result_ptr, format, args)
 #endif
   _IO_no_init ((_IO_FILE *) &sf._sbf, _IO_USER_LOCK, -1, NULL, NULL);
   _IO_JUMPS ((struct _IO_FILE_plus *) &sf._sbf) = &_IO_str_jumps;
-  INTUSE(_IO_str_init_static) (&sf, string, init_string_size, string);
+  _IO_str_init_static_internal (&sf, string, init_string_size, string);
   sf._sbf._f._flags &= ~_IO_USER_BUF;
   sf._s._allocate_buffer = (_IO_alloc_type) malloc;
   sf._s._free_buffer = (_IO_free_type) free;
--- libc/libio/vsnprintf.c.jj	2002-02-28 06:31:50.000000000 -0500
+++ libc/libio/vsnprintf.c	2003-05-26 08:45:19.000000000 -0400
@@ -1,4 +1,4 @@
-/* Copyright (C) 1994,1997,1999,2000,2001,2002 Free Software Foundation, Inc.
+/* Copyright (C) 1994,1997,1999-2003 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -126,7 +126,7 @@ _IO_vsnprintf (string, maxlen, format, a
   _IO_no_init (&sf.f._sbf._f, _IO_USER_LOCK, -1, NULL, NULL);
   _IO_JUMPS ((struct _IO_FILE_plus *) &sf.f._sbf) = &_IO_strn_jumps;
   string[0] = '\0';
-  INTUSE(_IO_str_init_static) (&sf.f, string, maxlen - 1, string);
+  _IO_str_init_static_internal (&sf.f, string, maxlen - 1, string);
   ret = INTUSE(_IO_vfprintf) ((_IO_FILE *) &sf.f._sbf, format, args);
 
   if (sf.f._sbf._f._IO_buf_base != sf.overflow_buf)
--- libc/libio/wstrops.c.jj	2002-08-27 17:19:42.000000000 -0400
+++ libc/libio/wstrops.c	2003-05-26 09:25:41.000000000 -0400
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993,1997,1998,1999,2001,2002 Free Software Foundation, Inc.
+/* Copyright (C) 1993,1997-1999,2001-2003 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -67,28 +67,20 @@ void
 _IO_wstr_init_static (fp, ptr, size, pstart)
      _IO_FILE *fp;
      wchar_t *ptr;
-     int size;
+     _IO_size_t size;
      wchar_t *pstart;
 {
+  wchar_t *end;
+  
   if (size == 0)
-    size = __wcslen (ptr);
-  else if (size < 0)
-    {
-      /* If size is negative 'the characters are assumed to
-	 continue indefinitely.'  This is kind of messy ... */
-      int s;
-      size = 512;
-      /* Try increasing powers of 2, as long as we don't wrap around. */
-      for (; s = 2*size, s > 0 && ptr + s > ptr && s < 0x4000000L; )
-	size = s;
-      /* Try increasing size as much as we can without wrapping around. */
-      for (s = size >> 1; s > 0; s >>= 1)
-	{
-	  if (ptr + size + s > ptr)
-	    size += s;
-	}
-    }
-  INTUSE(_IO_wsetb) (fp, ptr, ptr + size, 0);
+    end = ptr + __wcslen (ptr);
+  else if ((_IO_size_t) ptr + size * sizeof (wchar_t) > (_IO_size_t) ptr)
+    end = ptr + size;
+  else
+    /* Even for misaligned ptr make sure there is integral number of wide
+       characters.  */
+    end = ptr + (-1 - (_IO_size_t) ptr) / sizeof (wchar_t);
+  INTUSE(_IO_wsetb) (fp, ptr, end, 0);
 
   fp->_wide_data->_IO_write_base = ptr;
   fp->_wide_data->_IO_read_base = ptr;
@@ -96,29 +88,19 @@ _IO_wstr_init_static (fp, ptr, size, pst
   if (pstart)
     {
       fp->_wide_data->_IO_write_ptr = pstart;
-      fp->_wide_data->_IO_write_end = ptr + size;
+      fp->_wide_data->_IO_write_end = end;
       fp->_wide_data->_IO_read_end = pstart;
     }
   else
     {
       fp->_wide_data->_IO_write_ptr = ptr;
       fp->_wide_data->_IO_write_end = ptr;
-      fp->_wide_data->_IO_read_end = ptr + size;
+      fp->_wide_data->_IO_read_end = end;
     }
   /* A null _allocate_buffer function flags the strfile as being static. */
   (((_IO_strfile *) fp)->_s._allocate_buffer) =  (_IO_alloc_type)0;
 }
 
-void
-_IO_wstr_init_readonly (fp, ptr, size)
-     _IO_FILE *fp;
-     const char *ptr;
-     int size;
-{
-  _IO_wstr_init_static (fp, (wchar_t *) ptr, size, NULL);
-  fp->_IO_file_flags |= _IO_NO_WRITES;
-}
-
 _IO_wint_t
 _IO_wstr_overflow (fp, c)
      _IO_FILE *fp;
--- libc/stdio-common/tst-sprintf.c.jj	2001-12-14 02:17:17.000000000 -0500
+++ libc/stdio-common/tst-sprintf.c	2003-05-26 12:21:00.000000000 -0400
@@ -11,9 +11,30 @@ main (void)
   if (sprintf (buf, "%.0ls", L"foo") != 0
       || strlen (buf) != 0)
     {
-      puts ("sprintf (buf, \"%.0ls\", L\"foo\") produced some output\n");
+      puts ("sprintf (buf, \"%.0ls\", L\"foo\") produced some output");
       result = 1;
     }
 
+#define SIZE (1024*70000)
+#define STR(x) #x
+
+  char *dst = malloc (SIZE + 1);
+
+  if (dst == NULL)
+    {
+      puts ("memory allocation failure");
+      result = 1;
+    }
+  else
+    {
+      sprintf (dst, "%*s", SIZE, "");
+      if (strnlen (dst, SIZE + 1) != SIZE)
+	{
+	  puts ("sprintf (dst, \"%*s\", " STR(SIZE) ", \"\") did not produce enough output");
+	  result = 1;
+	}
+      free (dst);
+    }
+
   return result;
 }

	Jakub

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH] Fix snprintf
  2003-05-26 16:41 [PATCH] Fix snprintf Jakub Jelinek
@ 2003-05-27  7:40 ` Ulrich Drepper
  0 siblings, 0 replies; 2+ messages in thread
From: Ulrich Drepper @ 2003-05-27  7:40 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Roland McGrath, Glibc hackers

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Jakub Jelinek wrote:

> ATM sprintf creates at most 64M string, furthermore although snprintf
> is given size_t for max length, it is casted to int and thus it might be
> much smaller limit than the one given by the user (consider e.g.
> sprintf (buf, 0x100000010, fmt, args)).

I've applied the patch.  Thanks,

- -- 
- --------------.                        ,-.            444 Castro Street
Ulrich Drepper \    ,-----------------'   \ Mountain View, CA 94041 USA
Red Hat         `--' drepper at redhat.com `---------------------------
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.1 (GNU/Linux)

iD8DBQE+0xY72ijCOnn/RHQRAsqSAKCA8D14F/k6iTgxGH60EMKiCaazxQCgnFyy
hBcBC+KZWL5fjGJtmWoJhho=
=A7Dw
-----END PGP SIGNATURE-----

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2003-05-27  7:40 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-05-26 16:41 [PATCH] Fix snprintf Jakub Jelinek
2003-05-27  7:40 ` Ulrich Drepper

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).