From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 5272 invoked by alias); 26 May 2003 16:41:02 -0000 Mailing-List: contact libc-hacker-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-hacker-owner@sources.redhat.com Received: (qmail 5232 invoked from network); 26 May 2003 16:41:02 -0000 Received: from unknown (HELO localhost.localdomain) (195.113.19.66) by sources.redhat.com with SMTP; 26 May 2003 16:41:02 -0000 Received: from sunsite.ms.mff.cuni.cz (sunsite.mff.cuni.cz [127.0.0.1]) by localhost.localdomain (8.12.8/8.12.8) with ESMTP id h4QGexqO025034; Mon, 26 May 2003 18:40:59 +0200 Received: (from jakub@localhost) by sunsite.ms.mff.cuni.cz (8.12.8/8.12.8/Submit) id h4QGexNo025032; Mon, 26 May 2003 18:40:59 +0200 Date: Mon, 26 May 2003 16:41:00 -0000 From: Jakub Jelinek To: Ulrich Drepper , Roland McGrath Cc: Glibc hackers Subject: [PATCH] Fix snprintf Message-ID: <20030526164059.GA24872@sunsite.ms.mff.cuni.cz> Reply-To: Jakub Jelinek Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.4i X-SW-Source: 2003-05/txt/msg00032.txt.bz2 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 * 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 , 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