From patchwork Mon Jun 19 16:19:49 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 21103 Received: (qmail 86066 invoked by alias); 19 Jun 2017 16:19:48 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 86052 invoked by uid 89); 19 Jun 2017 16:19:47 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_HELO_PASS, T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 spammy=consumes, xxx X-HELO: mx1.redhat.com DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 0346785365 Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=fweimer@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 0346785365 Date: Mon, 19 Jun 2017 18:19:49 +0200 To: libc-alpha@sourceware.org Subject: [PATCH] vfprintf: Use struct scratch_buffer for positional arguments allocation User-Agent: Heirloom mailx 12.5 7/5/10 MIME-Version: 1.0 Message-Id: <20170619161949.12053402AEC0E@oldenburg.str.redhat.com> From: fweimer@redhat.com (Florian Weimer) 2017-06-19 Florian Weimer * stdio-common/vfprintf.c (printf_positional): Use struct scratch_buffer to allocate backing storage for the args_value, args_size, args_type arrays. diff --git a/stdio-common/vfprintf.c b/stdio-common/vfprintf.c index 76614fc..f0ea4fe 100644 --- a/stdio-common/vfprintf.c +++ b/stdio-common/vfprintf.c @@ -1627,15 +1627,17 @@ printf_positional (_IO_FILE *s, const CHAR_T *format, int readonly_format, CHAR_T *work_buffer, int save_errno, const char *grouping, THOUSANDS_SEP_T thousands_sep) { - /* For the argument descriptions, which may be allocated on the heap. */ - void *args_malloced = NULL; - /* For positional argument handling. */ struct scratch_buffer specsbuf; scratch_buffer_init (&specsbuf); struct printf_spec *specs = specsbuf.data; size_t specs_limit = specsbuf.length / sizeof (specs[0]); + /* Used as a backing store for args_value, args_size, args_type + below. */ + struct scratch_buffer argsbuf; + scratch_buffer_init (&argsbuf); + /* Array with information about the needed arguments. This has to be dynamically extensible. */ size_t nspecs = 0; @@ -1644,10 +1646,6 @@ printf_positional (_IO_FILE *s, const CHAR_T *format, int readonly_format, determine the size of the array needed to store the argument attributes. */ size_t nargs = 0; - size_t bytes_per_arg; - union printf_arg *args_value; - int *args_size; - int *args_type; /* Positional parameters refer to arguments directly. This could also determine the maximum number of arguments. Track the @@ -1695,38 +1693,29 @@ printf_positional (_IO_FILE *s, const CHAR_T *format, int readonly_format, /* Determine the number of arguments the format string consumes. */ nargs = MAX (nargs, max_ref_arg); - /* Calculate total size needed to represent a single argument across - all three argument-related arrays. */ - bytes_per_arg = (sizeof (*args_value) + sizeof (*args_size) - + sizeof (*args_type)); - /* Check for potential integer overflow. */ - if (__glibc_unlikely (nargs > INT_MAX / bytes_per_arg)) - { - __set_errno (EOVERFLOW); - done = -1; - goto all_done; - } - - /* Allocate memory for all three argument arrays. */ - if (__libc_use_alloca (nargs * bytes_per_arg)) - args_value = alloca (nargs * bytes_per_arg); - else - { - args_value = args_malloced = malloc (nargs * bytes_per_arg); - if (args_value == NULL) - { - done = -1; - goto all_done; - } - } - - /* Set up the remaining two arrays to each point past the end of the - prior array, since space for all three has been allocated now. */ - args_size = &args_value[nargs].pa_int; - args_type = &args_size[nargs]; - memset (args_type, s->_flags2 & _IO_FLAGS2_FORTIFY ? '\xff' : '\0', - nargs * sizeof (*args_type)); + union printf_arg *args_value; + int *args_size; + int *args_type; + { + /* Calculate total size needed to represent a single argument + across all three argument-related arrays. */ + size_t bytes_per_arg + = sizeof (*args_value) + sizeof (*args_size) + sizeof (*args_type); + if (!scratch_buffer_set_array_size (&argsbuf, nargs, bytes_per_arg)) + { + done = -1; + goto all_done; + } + args_value = argsbuf.data; + /* Set up the remaining two arrays to each point past the end of + the prior array, since space for all three has been allocated + now. */ + args_size = &args_value[nargs].pa_int; + args_type = &args_size[nargs]; + memset (args_type, s->_flags2 & _IO_FLAGS2_FORTIFY ? '\xff' : '\0', + nargs * sizeof (*args_type)); + } /* XXX Could do sanity check here: If any element in ARGS_TYPE is still zero after this loop, format is invalid. For now we @@ -1966,8 +1955,7 @@ printf_positional (_IO_FILE *s, const CHAR_T *format, int readonly_format, - specs[nspecs_done].end_of_fmt); } all_done: - if (__glibc_unlikely (args_malloced != NULL)) - free (args_malloced); + scratch_buffer_free (&argsbuf); scratch_buffer_free (&specsbuf); return done; }