From patchwork Tue Jan 5 18:58:13 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella Netto X-Patchwork-Id: 41644 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 8EB30393C846; Tue, 5 Jan 2021 18:58:35 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 8EB30393C846 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1609873115; bh=BBIlmvxYRYeG07t5P0xg/7HaVci5AZPWI1oqaYU/0l0=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=MREx3xVdupAh+nEAlfl5LRrv379T715TAOCmwJI6cpef0f1sYxZkdDsnctMlSfJow RXrz3tFE5nPWoYGzwYbtjLWKUbnkYgxSp0d6Q8vFKs84E/uvzJIfk0nz7oVfKQ25b2 oTcyPyVQ8QuEjIyCsPxhPmb8M1YeYaDX8IHodxnM= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-qk1-x72b.google.com (mail-qk1-x72b.google.com [IPv6:2607:f8b0:4864:20::72b]) by sourceware.org (Postfix) with ESMTPS id D91533898532 for ; Tue, 5 Jan 2021 18:58:28 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org D91533898532 Received: by mail-qk1-x72b.google.com with SMTP id h4so314385qkk.4 for ; Tue, 05 Jan 2021 10:58:28 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=BBIlmvxYRYeG07t5P0xg/7HaVci5AZPWI1oqaYU/0l0=; b=Qc23C+Zk0JlpZtvl93jJRVezTq797VlZjBwvU5RHALdA8Om0yRBRAMVDJpHqDIKkE8 9a8tSN/z3ww+DwvGFc8QWCACNu8KLmtUcLQDHOYXtPkQER4XoonfPdJYQpjKbZg0GDRI ODLYisIKcv38pKLc13FtkEjsYRTYDd0M7mfCSNT7BGdZlZPin4jfoqUK8cIHz9IySsmk mcWxLjISoi4ydoWCrECZtEm8HWY/0qzmh2M/QEaOM1HKRO9diIOQlEJki0wVZ9pDR8SZ UCpTEjucWVVO7jZZlTT+cbbNSNy8P7QWr+l4uirvAXNUbRDfQ5XRtzAZ8N3MQd+QjWvp zRfA== X-Gm-Message-State: AOAM533P6w3WR3tX0uh9rp4LHchDbgVGn477bYeO1ytb5eWiCs1Gh1+U PVReqp3b6nRrj2Q7fe+vv+amdMVqLcYg6Q== X-Google-Smtp-Source: ABdhPJxeN/7jTNf+g1N0graT1uBkTG0pQ+wymfnz2f0770kXyj13QGfgVaWPBNScjCcapgmJ1gPlyg== X-Received: by 2002:ae9:ed41:: with SMTP id c62mr890109qkg.111.1609873107842; Tue, 05 Jan 2021 10:58:27 -0800 (PST) Received: from localhost.localdomain ([177.194.48.209]) by smtp.googlemail.com with ESMTPSA id t68sm67792qkd.35.2021.01.05.10.58.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Jan 2021 10:58:27 -0800 (PST) To: libc-alpha@sourceware.org, Paul Eggert , bug-gnulib@gnu.org Subject: [PATCH 1/8] malloc: Add specialized dynarray for C strings Date: Tue, 5 Jan 2021 15:58:13 -0300 Message-Id: <20210105185820.3796657-2-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210105185820.3796657-1-adhemerval.zanella@linaro.org> References: <20210105185820.3796657-1-adhemerval.zanella@linaro.org> MIME-Version: 1.0 X-Spam-Status: No, score=-13.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Adhemerval Zanella via Libc-alpha From: Adhemerval Zanella Netto Reply-To: Adhemerval Zanella Errors-To: libc-alpha-bounces@sourceware.org Sender: "Libc-alpha" This patch adds an specialized dynarray to manage C strings using the dynarray internal implementation. It uses some private fields from dynarray and thus it provided specific files to access and manage the internal string buffer. For instance: struct char_array str; // str == "testing" char_array_init_str (&str, "testing"); // c == 's' char c = char_array_pos (&str, 2); // str = "testing2" char_array_set_str (&str, "testing2"); // str = "testig2" char_array_erase (&str, 5); // str = "123testig2"; char_array_prepend_str (&str, "123"); // len = 10; size_t len = char_array_length (&str); // str = "123testig2456"; char_array_append_str (&str, "456"); // str = "123test789"; char_array_replace_str_pos (&str, 7, "789", 3); The provided function are not extensive and meant mainly to be use in subsequent glob implementation cleanup. For internal object consistency only the function provided by char_array.c should be used, including internal object manipulation. To check for possible overflows in internal size manipulation a new function, check_add_wrapv_size_t, is added on malloc-internal. It basically return whether the addition of two size_t overflows. Checked on x86_64-linux-gnu. * malloc/Makefile (test-internal): Add tst-char_array. (routines): Add dynarray_overflow_failure and char_array-impl. * malloc/Versions [GLIBC_PRIVATE] (libc): Add __libc_dynarray_overflow_failure, __char_array_set_str_size, __char_array_erase, __char_array_prepend_str_size, and __char_array_replace_str_pos. * malloc/char_array-impl.c: New file. * malloc/char_array-skeleton.c: Likewise. * malloc/char_array.h: Likewise. * malloc/tst-char-array.c: Likewise. * malloc/dynarray_overflow_failure.c: Likewise. * malloc/malloc-internal.h (check_add_overflow_size_t): New function. Signed-off-by: Adhemerval Zanella --- malloc/Makefile | 4 +- malloc/Versions | 7 + malloc/char_array-impl.c | 57 ++++++ malloc/char_array-skeleton.c | 288 +++++++++++++++++++++++++++++ malloc/char_array.h | 53 ++++++ malloc/dynarray.h | 9 + malloc/dynarray_overflow_failure.c | 31 ++++ malloc/malloc-internal.h | 14 ++ malloc/tst-char_array.c | 112 +++++++++++ 9 files changed, 574 insertions(+), 1 deletion(-) create mode 100644 malloc/char_array-impl.c create mode 100644 malloc/char_array-skeleton.c create mode 100644 malloc/char_array.h create mode 100644 malloc/dynarray_overflow_failure.c create mode 100644 malloc/tst-char_array.c diff --git a/malloc/Makefile b/malloc/Makefile index 583bbefb0d..850104a763 100644 --- a/malloc/Makefile +++ b/malloc/Makefile @@ -54,6 +54,7 @@ tests-internal += \ tst-dynarray \ tst-dynarray-fail \ tst-dynarray-at-fail \ + tst-char_array ifneq (no,$(have-tunables)) tests += tst-malloc-usable-tunables tst-mxfast @@ -77,7 +78,7 @@ routines = malloc morecore mcheck mtrace obstack reallocarray \ scratch_buffer_dupfree \ scratch_buffer_grow scratch_buffer_grow_preserve \ scratch_buffer_set_array_size \ - dynarray_at_failure \ + dynarray_at_failure dynarray_overflow_failure \ dynarray_emplace_enlarge \ dynarray_finalize \ dynarray_resize \ @@ -87,6 +88,7 @@ routines = malloc morecore mcheck mtrace obstack reallocarray \ alloc_buffer_copy_bytes \ alloc_buffer_copy_string \ alloc_buffer_create_failure \ + char_array-impl install-lib := libmcheck.a non-lib.a := libmcheck.a diff --git a/malloc/Versions b/malloc/Versions index 6693c46ee2..52d7a97388 100644 --- a/malloc/Versions +++ b/malloc/Versions @@ -85,6 +85,7 @@ libc { # dynarray support __libc_dynarray_at_failure; + __libc_dynarray_overflow_failure; __libc_dynarray_emplace_enlarge; __libc_dynarray_finalize; __libc_dynarray_resize; @@ -96,5 +97,11 @@ libc { __libc_alloc_buffer_copy_bytes; __libc_alloc_buffer_copy_string; __libc_alloc_buffer_create_failure; + + # char_array support + __char_array_set_str_size; + __char_array_erase; + __char_array_prepend_str_size; + __char_array_replace_str_pos; } } diff --git a/malloc/char_array-impl.c b/malloc/char_array-impl.c new file mode 100644 index 0000000000..3aef1f756d --- /dev/null +++ b/malloc/char_array-impl.c @@ -0,0 +1,57 @@ +/* Specialized dynarray for C strings. Implementation file. + Copyright (C) 2018 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 + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include + +void +__char_array_set_str_size (struct dynarray_header *header, const char *str, + size_t size) +{ + *((char *) mempcpy (header->array, str, size)) = '\0'; + header->used = size + 1; +} +libc_hidden_def (__char_array_set_str_size) + +void +__char_array_erase (struct dynarray_header *header, size_t pos) +{ + char *ppos = header->array + pos; + char *lpos = header->array + header->used; + ptrdiff_t size = lpos - ppos; + memmove (ppos, ppos + 1, size); + header->used--; +} +libc_hidden_def (__char_array_erase) + +void +__char_array_prepend_str_size (struct dynarray_header *header, + const char *str, size_t size, size_t used) +{ + memmove (header->array + size, header->array, used); + memcpy (header->array, str, size); +} +libc_hidden_def (__char_array_prepend_str_size) + +void +__char_array_replace_str_pos (struct dynarray_header *header, size_t pos, + const char *str, size_t len) +{ + char *start = header->array + pos; + *(char *) mempcpy (start, str, len) = '\0'; +} +libc_hidden_def (__char_array_replace_str_pos) diff --git a/malloc/char_array-skeleton.c b/malloc/char_array-skeleton.c new file mode 100644 index 0000000000..4d9e4c0d4e --- /dev/null +++ b/malloc/char_array-skeleton.c @@ -0,0 +1,288 @@ +/* Specialized dynarray for C strings. + Copyright (C) 2018 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 + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +/* This file provides a dynamic C string with an initial stack allocated + buffer. Since it is based on dynarray, it provides dynamic size + expansion and heap usage for large strings. + + The following parameters are optional: + + CHAR_ARRAY_INITIAL_SIZE + The size of the statically allocated array (default is 256). It will + be used to define DYNARRAY_INITIAL_SIZE. + + The following functions are provided: + + bool char_array_init_empty (struct char_array *); + bool char_array_init_str (struct char_array *, const char *); + bool char_array_init_str_size (struct char_array *, const char *, size_t); + bool char_array_is_empty (struct char_array *); + const char *char_array_str (struct char_array *); + char char_array_pos (struct char_array *, size_t); + size_t char_array_length (struct char_array *); + bool char_array_set_str (struct char_array *, const char *); + bool char_array_set_str_size (struct char_array *, const char *, size_t); + void char_array_erase (struct char_array *, size_t); + bool char_array_crop (struct char_array *, size_t); + bool char_array_prepend_str (struct char_array *, const char *); + bool char_array_append_str (struct char_array *, const char *); + bool char_array_append_char (struct char_array *array, char c); + bool char_array_replace_str_pos (struct char_array *, size_t, const char *, + size_t); + + For instance: + + struct char_array str; + + // str == "testing" + char_array_init_str (&str, "testing"); + + // c == 's' + char c = char_array_pos (&str, 2); + + // str = "testing2" + char_array_set_str (&str, "testing2"); + + // str = "testig2" + char_array_erase (&str, 5); + + // str = "123testig2"; + char_array_prepend_str (&str, "123"); + + // len = 10; + size_t len = char_array_length (&str); + + // str = "123testig2456"; + char_array_append_str (&str, "456"); + + // str = "123test789"; + char_array_replace_str_pos (&str, 7, "789", 3); + */ + +#define DYNARRAY_STRUCT char_array +#define DYNARRAY_ELEMENT char +#define DYNARRAY_PREFIX char_array_ +#ifndef CHAR_ARRAY_INITIAL_SIZE +# define CHAR_ARRAY_INITIAL_SIZE 256 +#endif +#define DYNARRAY_INITIAL_SIZE CHAR_ARRAY_INITIAL_SIZE +#include + +#include +#include + +/* Return a const char for the internal C string handled by 'array'. */ +__attribute__ ((unused, nonnull (1))) +static const char * +char_array_str (const struct char_array *array) +{ + return array->dynarray_header.array; +} + +/* Return the character at position 'pos' from the char_array 'array'. */ +__attribute__ ((unused, nonnull (1))) +static char +char_array_pos (struct char_array *array, size_t pos) +{ + return *char_array_at (array, pos); +} + +/* Calculate the length of the string, excluding the terminating null. */ +__attribute__ ((unused, nonnull (1))) +static size_t +char_array_length (const struct char_array *array) +{ + /* Exclude the final '\0'. */ + return array->dynarray_header.used - 1; +} + +/* Copy up 'size' bytes from string 'str' to char_array 'array'. A final + '\0' is appended in the char_array. */ +__attribute__ ((unused, nonnull (1, 2))) +static bool +char_array_set_str_size (struct char_array *array, const char *str, + size_t size) +{ + size_t newsize; + if (check_add_overflow_size_t (size, 1, &newsize)) + __libc_dynarray_overflow_failure (size, 1); + + if (!char_array_resize (array, newsize)) + return false; + + __char_array_set_str_size (&array->dynarray_abstract, str, size); + return true; +} + +/* Copy the contents of string 'str' to char_array 'array', including the + final '\0'. */ +__attribute__ ((unused, nonnull (1, 2))) +static bool +char_array_set_str (struct char_array *array, const char *str) +{ + return char_array_set_str_size (array, str, strlen (str)); +} + +__attribute__ ((unused, nonnull (1, 2))) +static bool +char_array_set_array (struct char_array *array, const struct char_array *orig) +{ + return char_array_set_str_size (array, char_array_str (orig), + char_array_length (orig)); +} + +/* Initialize the char_array 'array' and sets it to an empty string (""). */ +__attribute__ ((unused, nonnull (1))) +static bool +char_array_init_empty (struct char_array *array) +{ + char_array_init (array); + return char_array_set_str (array, ""); +} + +/* Initialize the char_array 'array' and copy the content of string 'str'. */ +__attribute__ ((unused, nonnull (1, 2))) +static bool +char_array_init_str (struct char_array *array, const char *str) +{ + char_array_init (array); + return char_array_set_str (array, str); +} + +/* Initialize the char_array 'array' and copy the content of string 'str' + up to 'size' characteres. */ +__attribute__ ((unused, nonnull (1, 2))) +static bool +char_array_init_str_size (struct char_array *array, const char *str, + size_t size) +{ + char_array_init (array); + return char_array_set_str_size (array, str, size); +} + +/* Return if the char_array contain any characteres. */ +__attribute__ ((unused, nonnull (1))) +static bool +char_array_is_empty (struct char_array *array) +{ + return *char_array_begin (array) == '\0'; +} + +/* Remove the byte at position 'pos' from char_array 'array'. The contents + are moved internally if the position is not at the end of the internal + buffer. */ +__attribute__ ((unused, nonnull (1))) +static bool +char_array_erase (struct char_array *array, size_t pos) +{ + if (pos >= array->dynarray_header.used - 1) + return false; + + __char_array_erase (&array->dynarray_abstract, pos); + return true; +} + +/* Resize the char_array 'array' to size 'count' maintaining the ending + '\0' byte. */ +__attribute__ ((unused, nonnull (1))) +static bool +char_array_crop (struct char_array *array, size_t size) +{ + if (size >= (array->dynarray_header.used - 1) + || !char_array_resize (array, size + 1)) + return false; + + array->dynarray_header.array[size] = '\0'; + return true; +} + +/* Prepend the contents of string 'str' to char_array 'array', including the + final '\0' byte. */ +__attribute__ ((unused, nonnull (1, 2))) +static bool +char_array_prepend_str (struct char_array *array, const char *str) +{ + size_t size = strlen (str); + /* Resizing the array might change its used elements and we need below + to correct copy the elements. */ + size_t used = array->dynarray_header.used; + + size_t newsize; + if (check_add_overflow_size_t (used, size, &newsize)) + __libc_dynarray_overflow_failure (used, size); + + /* Make room for the string and copy it. */ + if (!char_array_resize (array, newsize)) + return false; + __char_array_prepend_str_size (&array->dynarray_abstract, str, size, used); + return true; +} + +/* Append the contents of string 'str' to char_array 'array, including the + final '\0' byte. */ +__attribute__ ((unused, nonnull (1, 2))) +static bool +char_array_append_str (struct char_array *array, const char *str) +{ + size_t size = strlen (str); + /* Resizing the array might change its used elements and it used it below + to correct copy the elements. */ + size_t used = array->dynarray_header.used - 1; + + /* 'used' does account for final '\0', so there is no need to add + an extra element to calculate the final required size. */ + size_t newsize; + if (check_add_overflow_size_t (used + 1, size, &newsize)) + __libc_dynarray_overflow_failure (used + 1, size); + + if (!char_array_resize (array, newsize)) + return false; + + /* Start to append at '\0' up to string length and add a final '\0'. */ + *(char*) mempcpy (array->dynarray_header.array + used, str, size) = '\0'; + return true; +} + +/* Append the character 'c' on char_array 'array'. */ +__attribute__ ((unused, nonnull (1))) +static bool +char_array_append_char (struct char_array *array, char c) +{ + return char_array_append_str (array, (const char[]) { c, '\0' }); +} + +/* Replace the contents starting of position 'pos' of char_array 'array' + with the contents of string 'str' up to 'len' bytes. A final '\0' + is appended in the string. */ +__attribute__ ((unused, nonnull (1, 3))) +static bool +char_array_replace_str_pos (struct char_array *array, size_t pos, + const char *str, size_t len) +{ + if (pos > array->dynarray_header.used) + __libc_dynarray_at_failure (array->dynarray_header.used, pos); + + size_t newsize; + if (check_add_overflow_size_t (pos, len, &newsize) + || check_add_overflow_size_t (newsize, 1, &newsize) + || !char_array_resize (array, newsize)) + return false; + + __char_array_replace_str_pos (&array->dynarray_abstract, pos, str, len); + return true; +} diff --git a/malloc/char_array.h b/malloc/char_array.h new file mode 100644 index 0000000000..93df0d9fbd --- /dev/null +++ b/malloc/char_array.h @@ -0,0 +1,53 @@ +/* Specialized dynarray for C strings. Shared definitions. + Copyright (C) 2018 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 + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef _CHAR_ARRAY_H +#define _CHAR_ARRAY_H + +#include + +/* Internal funciton. Set the dynarray to the content of the string STR up + to SIZE bytes. The dynarray must be resized previously. */ +void __char_array_set_str_size (struct dynarray_header *, const char *str, + size_t size); + +/* Internal function. Remove the character at position POS from dynarray. + The position must be a valid one. */ +void __char_array_erase (struct dynarray_header *, size_t pos); + +/* Internal function. Prepend the content of string STR up to SIZE bytes to + dynarray by moving USED bytes forward. The dynarray must be resized + previously. */ +void __char_array_prepend_str_size (struct dynarray_header *, + const char *str, size_t size, + size_t used); + +/* Internal function. Replace the content of dynarray starting at position + POS with the content of string STR up to LEN bytes. The dynarray must + be resize previously and STR must contain at least LEN bytes. */ +void __char_array_replace_str_pos (struct dynarray_header *, size_t pos, + const char *str, size_t len); + +#ifndef _ISOMAC +libc_hidden_proto (__char_array_set_str_size) +libc_hidden_proto (__char_array_erase) +libc_hidden_proto (__char_array_prepend_str_size) +libc_hidden_proto (__char_array_replace_str_pos) +#endif + +#endif diff --git a/malloc/dynarray.h b/malloc/dynarray.h index 24ca1620d2..ddff3e7855 100644 --- a/malloc/dynarray.h +++ b/malloc/dynarray.h @@ -168,12 +168,21 @@ bool __libc_dynarray_finalize (struct dynarray_header *list, void *scratch, void __libc_dynarray_at_failure (size_t size, size_t index) __attribute__ ((noreturn)); +/* Internal function. Terminate the process after an overflow in + new size allocation. SIZE is the current number of elements in + dynamic array and INCR is the new elements to add on current + size. */ +void __libc_dynarray_overflow_failure (size_t size, size_t incr) + __attribute__ ((noreturn)); + #ifndef _ISOMAC libc_hidden_proto (__libc_dynarray_emplace_enlarge) libc_hidden_proto (__libc_dynarray_resize) libc_hidden_proto (__libc_dynarray_resize_clear) libc_hidden_proto (__libc_dynarray_finalize) libc_hidden_proto (__libc_dynarray_at_failure) +libc_hidden_proto (__libc_dynarray_overflow_failure) + #endif #endif /* _DYNARRAY_H */ diff --git a/malloc/dynarray_overflow_failure.c b/malloc/dynarray_overflow_failure.c new file mode 100644 index 0000000000..2bcef25efd --- /dev/null +++ b/malloc/dynarray_overflow_failure.c @@ -0,0 +1,31 @@ +/* Report an dynamic array size overflow condition. + Copyright (C) 2018 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 + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include + +void +__libc_dynarray_overflow_failure (size_t size, size_t incr) +{ + char buf[200]; + __snprintf (buf, sizeof (buf), "Fatal glibc error: " + "new size overflows (old %zu and increment %zu)\n", + size, incr); + __libc_fatal (buf); +} +libc_hidden_def (__libc_dynarray_overflow_failure) diff --git a/malloc/malloc-internal.h b/malloc/malloc-internal.h index 258f29584e..2d13868ed9 100644 --- a/malloc/malloc-internal.h +++ b/malloc/malloc-internal.h @@ -77,4 +77,18 @@ void __malloc_arena_thread_freeres (void) attribute_hidden; /* Activate a standard set of debugging hooks. */ void __malloc_check_init (void) attribute_hidden; +/* Set *R = A + B. Return true if the answer is mathematically incorrect due + to overflow; in this case, *R is the low order bits of the correct + answer. */ +static inline bool +check_add_overflow_size_t (size_t a, size_t b, size_t *r) +{ +#if __GNUC__ >= 5 + return __builtin_add_overflow (a, b, r); +#else + *r = a + b; + return *r < a; +#endif +} + #endif /* _MALLOC_INTERNAL_H */ diff --git a/malloc/tst-char_array.c b/malloc/tst-char_array.c new file mode 100644 index 0000000000..745ecf4c98 --- /dev/null +++ b/malloc/tst-char_array.c @@ -0,0 +1,112 @@ +/* Test for char_array. + Copyright (C) 2018 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 + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include + +#include + +#include +#include +#include +#include +#include + +static int +do_test (void) +{ + mtrace (); + + { + struct char_array str; + TEST_VERIFY_EXIT (char_array_init_empty (&str) == true); + TEST_VERIFY_EXIT (char_array_length (&str) == 0); + TEST_VERIFY_EXIT (char_array_is_empty (&str) == true); + TEST_VERIFY_EXIT (strcmp (char_array_str (&str), "") == 0); + char_array_free (&str); + } + + { + struct char_array str; + TEST_VERIFY_EXIT (char_array_init_str (&str, "testing")); + TEST_VERIFY_EXIT (char_array_length (&str) == strlen ("testing")); + TEST_VERIFY_EXIT (char_array_pos (&str, 2) == 's'); + TEST_VERIFY_EXIT (char_array_is_empty (&str) == false); + TEST_VERIFY_EXIT (strcmp (char_array_str (&str), "testing") == 0); + char_array_free (&str); + } + + { + struct char_array str; + TEST_VERIFY_EXIT (char_array_init_str_size (&str, "testing", 4)); + TEST_VERIFY_EXIT (char_array_length (&str) == 4); + TEST_VERIFY_EXIT (char_array_pos (&str, 2) == 's'); + TEST_VERIFY_EXIT (char_array_is_empty (&str) == false); + TEST_VERIFY_EXIT (strcmp (char_array_str (&str), "test") == 0); + char_array_free (&str); + } + + { + struct char_array str; + TEST_VERIFY_EXIT (char_array_init_str (&str, "testing")); + TEST_VERIFY_EXIT (char_array_set_str (&str, "abcdef")); + TEST_VERIFY_EXIT (strcmp (char_array_str (&str), "abcdef") == 0); + TEST_VERIFY_EXIT (char_array_set_str_size (&str, "abcdef", 4)); + TEST_VERIFY_EXIT (strcmp (char_array_str (&str), "abcd") == 0); + char_array_free (&str); + } + + { + struct char_array str; + TEST_VERIFY_EXIT (char_array_init_str (&str, "testing")); + TEST_VERIFY_EXIT (char_array_erase (&str, 4) == true); + TEST_VERIFY_EXIT (char_array_length (&str) == strlen ("testing") - 1); + TEST_VERIFY_EXIT (strcmp (char_array_str (&str), "testng") == 0); + TEST_VERIFY_EXIT (char_array_erase (&str, char_array_length (&str)) + == false); + TEST_VERIFY_EXIT (char_array_length (&str) == strlen ("testing") - 1); + TEST_VERIFY_EXIT (char_array_erase (&str, char_array_length (&str) - 1) + == true); + TEST_VERIFY_EXIT (char_array_length (&str) == strlen ("testing") - 2); + TEST_VERIFY_EXIT (strcmp (char_array_str (&str), "testn") == 0); + char_array_free (&str); + } + + { + struct char_array str; + TEST_VERIFY_EXIT (char_array_init_str (&str, "test")); + TEST_VERIFY_EXIT (char_array_prepend_str (&str, "123")); + TEST_VERIFY_EXIT (strcmp (char_array_str (&str), "123test") == 0); + TEST_VERIFY_EXIT (char_array_length (&str) == strlen ("123test")); + TEST_VERIFY_EXIT (char_array_append_str (&str, "456")); + TEST_VERIFY_EXIT (strcmp (char_array_str (&str), "123test456") == 0); + TEST_VERIFY_EXIT (char_array_length (&str) == strlen ("123test456")); + TEST_VERIFY_EXIT (char_array_replace_str_pos (&str, 7, "789", 3)); + TEST_VERIFY_EXIT (strcmp (char_array_str (&str), "123test789") == 0); + TEST_VERIFY_EXIT (char_array_length (&str) == strlen ("123test789")); + TEST_VERIFY_EXIT (char_array_crop (&str, 7)); + TEST_VERIFY_EXIT (char_array_length (&str) == 7); + TEST_VERIFY_EXIT (strcmp (char_array_str (&str), "123test") == 0); + TEST_VERIFY_EXIT (char_array_append_char (&str, '4')); + TEST_VERIFY_EXIT (strcmp (char_array_str (&str), "123test4") == 0); + char_array_free (&str); + } + + return 0; +} + +#include From patchwork Tue Jan 5 18:58:14 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella Netto X-Patchwork-Id: 41643 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 6DC42393BC2D; Tue, 5 Jan 2021 18:58:34 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 6DC42393BC2D DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1609873114; bh=5hBRwF/R7b2diX1WzX/5N67vMXtF1GzyzvuRqHdpVU0=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=Wi9LTaLuNnzbkQDUFtl1DGJaR7vGYBsnxE42wumWhV4kcc60KXft9bBkS+pbsylyj IGZvcMJNiLkfOs1Y8uqfu8iOf5ta4ZtipHhcwKvfPcTZl0Nk62ai9e4S8G3eOLD50y XpVKzwczof/PfEFXrsUAQS8Sc/T9XkItGJHIIgyI= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-qv1-xf36.google.com (mail-qv1-xf36.google.com [IPv6:2607:f8b0:4864:20::f36]) by sourceware.org (Postfix) with ESMTPS id C6CE93894C09 for ; Tue, 5 Jan 2021 18:58:30 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org C6CE93894C09 Received: by mail-qv1-xf36.google.com with SMTP id et9so124848qvb.10 for ; Tue, 05 Jan 2021 10:58:30 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=5hBRwF/R7b2diX1WzX/5N67vMXtF1GzyzvuRqHdpVU0=; b=QFu7ICddT5NFxVNFXueykcWo7v+Zr1+ntHd0/S1U4WwUqV74hiDXgBjye1GwTqquLk CpRFMxCX8lHWUxMPQah3W9gDp+6l4PlUHJ4OrlGC7exsuDkqDcylpFxDZJsgoqBuS82L btioE5MU8mOQJ0cvSicVVXRdMbzA7t+LJai16UJvKEU7G46ENSlw7u9W79mYKtDAuC+F S7jAqS9c5NhU2Exq+UFEUrpN5siKegt+yPpXV13otJx5EnJN2AssUj45fDCZ1mlC59HT nrMdxLeFW7QfpVfCWGLrRJDy8afh2daPMtZTiwoBT0GC+Q4T6DDTad3yLRNPhm4KdHiu v6zw== X-Gm-Message-State: AOAM5338+ODA0DRkENhINEOxyVaE9PtEypM5SQXsr7pJj0DIWiFu4C6Z VR//yYdu2P8mCKWEpPFH6lHo+Rq/ynv8Ow== X-Google-Smtp-Source: ABdhPJzTg0Byrdf2hPXD1bGFM69k3zTInomgUbL3gS9gUWAMAJt/KLsCpflx9mzfkwsh+d2o6xJsPg== X-Received: by 2002:ad4:55f2:: with SMTP id bu18mr930006qvb.27.1609873109804; Tue, 05 Jan 2021 10:58:29 -0800 (PST) Received: from localhost.localdomain ([177.194.48.209]) by smtp.googlemail.com with ESMTPSA id t68sm67792qkd.35.2021.01.05.10.58.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Jan 2021 10:58:29 -0800 (PST) To: libc-alpha@sourceware.org, Paul Eggert , bug-gnulib@gnu.org Subject: [PATCH 2/8] posix: Use char_array for internal glob dirname Date: Tue, 5 Jan 2021 15:58:14 -0300 Message-Id: <20210105185820.3796657-3-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210105185820.3796657-1-adhemerval.zanella@linaro.org> References: <20210105185820.3796657-1-adhemerval.zanella@linaro.org> MIME-Version: 1.0 X-Spam-Status: No, score=-13.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Adhemerval Zanella via Libc-alpha From: Adhemerval Zanella Netto Reply-To: Adhemerval Zanella Errors-To: libc-alpha-bounces@sourceware.org Sender: "Libc-alpha" This is the first patch of the set to remove alloca usage on glob implementation. Internal path to search for file might expand to a non static directory derived from pattern for some difference cases (GLOB_NOESCAPE, GNU GLOB_TILDE) and to allow a non-static dirname path glob uses a lot of boilerplate code to manage the buffer (which is either allocated using alloca or malloc depending both to size requested and the total alloca_used). The patch changes to use the char_array struct with the default size (256 bytes). It simplifies all the allocation code by using char_array one and every internal buffer access is done using char_array provided functions. No functional changes are expected. Checked on x86_64-linux-gnu. --- posix/glob.c | 275 +++++++++++++++++++++------------------------------ 1 file changed, 111 insertions(+), 164 deletions(-) diff --git a/posix/glob.c b/posix/glob.c index 32c88e5d15..8c6e1914c5 100644 --- a/posix/glob.c +++ b/posix/glob.c @@ -85,6 +85,7 @@ #include #include #include +#include static const char *next_brace_sub (const char *begin, int flags) __THROWNL; @@ -298,16 +299,15 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), glob_t *pglob) { const char *filename; - char *dirname = NULL; size_t dirlen; int status; size_t oldcount; int meta; - int dirname_modified; - int malloc_dirname = 0; glob_t dirs; int retval = 0; size_t alloca_used = 0; + struct char_array dirname; + bool dirname_modified; if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0) { @@ -315,6 +315,10 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), return -1; } + /* Default char array is stack allocated, so there is no need to check + if setting the initial '\0' succeeds. */ + char_array_init_empty (&dirname); + /* POSIX requires all slashes to be matched. This means that with a trailing slash we must match only directories. */ if (pattern[0] && pattern[strlen (pattern) - 1] == '/') @@ -335,12 +339,12 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), size_t i; if (pglob->gl_offs >= ~((size_t) 0) / sizeof (char *)) - return GLOB_NOSPACE; + goto err_nospace; pglob->gl_pathv = (char **) malloc ((pglob->gl_offs + 1) * sizeof (char *)); if (pglob->gl_pathv == NULL) - return GLOB_NOSPACE; + goto err_nospace; for (i = 0; i <= pglob->gl_offs; ++i) pglob->gl_pathv[i] = NULL; @@ -392,7 +396,7 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), { onealt = malloc (pattern_len); if (onealt == NULL) - return GLOB_NOSPACE; + goto err_nospace; } /* We know the prefix for all sub-patterns. */ @@ -454,7 +458,8 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), globfree (pglob); pglob->gl_pathc = 0; } - return result; + retval = result; + goto out; } if (*next == '}') @@ -471,9 +476,10 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), if (pglob->gl_pathc != firstc) /* We found some entries. */ - return 0; + retval = 0; else if (!(flags & (GLOB_NOCHECK|GLOB_NOMAGIC))) - return GLOB_NOMATCH; + retval = GLOB_NOMATCH; + goto out; } } @@ -492,14 +498,15 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), filename = strchr (pattern, ':'); #endif /* __MSDOS__ || WINDOWS32 */ - dirname_modified = 0; + dirname_modified = false; if (filename == NULL) { /* This can mean two things: a simple name or "~name". The latter case is nothing but a notation for a directory. */ if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && pattern[0] == '~') { - dirname = (char *) pattern; + if (!char_array_set_str (&dirname, pattern)) + goto err_nospace; dirlen = strlen (pattern); /* Set FILENAME to NULL as a special flag. This is ugly but @@ -516,7 +523,8 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), } filename = pattern; - dirname = (char *) "."; + if (!char_array_set_str (&dirname, ".")) + goto err_nospace; dirlen = 0; } } @@ -525,13 +533,13 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), && (flags & GLOB_NOESCAPE) == 0)) { /* "/pattern" or "\\/pattern". */ - dirname = (char *) "/"; + if (!char_array_set_str (&dirname, "/")) + goto err_nospace; dirlen = 1; ++filename; } else { - char *newp; dirlen = filename - pattern; #if defined __MSDOS__ || defined WINDOWS32 if (*filename == ':' @@ -545,31 +553,26 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), /* For now, disallow wildcards in the drive spec, to prevent infinite recursion in glob. */ if (__glob_pattern_p (drive_spec, !(flags & GLOB_NOESCAPE))) - return GLOB_NOMATCH; + { + retval = GLOB_NOMATCH; + goto out; + } /* If this is "d:pattern", we need to copy ':' to DIRNAME as well. If it's "d:/pattern", don't remove the slash from "d:/", since "d:" and "d:/" are not the same.*/ } #endif - if (glob_use_alloca (alloca_used, dirlen + 1)) - newp = alloca_account (dirlen + 1, alloca_used); - else - { - newp = malloc (dirlen + 1); - if (newp == NULL) - return GLOB_NOSPACE; - malloc_dirname = 1; - } - *((char *) mempcpy (newp, pattern, dirlen)) = '\0'; - dirname = newp; + if (!char_array_set_str_size (&dirname, pattern, dirlen)) + goto err_nospace; ++filename; #if defined __MSDOS__ || defined WINDOWS32 bool drive_root = (dirlen > 1 - && (dirname[dirlen - 1] == ':' - || (dirlen > 2 && dirname[dirlen - 2] == ':' - && dirname[dirlen - 1] == '/'))); + && (char_array_pos (&dirname, dirlen - 1) != ':' + || (dirlen > 2 + && char_array_pos (&dirname, dirlen - 2) != ':' + && char_array_pos (&dirname, dirlen - 1) != '/'))); #else bool drive_root = false; #endif @@ -578,20 +581,24 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), /* "pattern/". Expand "pattern", appending slashes. */ { int orig_flags = flags; - if (!(flags & GLOB_NOESCAPE) && dirname[dirlen - 1] == '\\') + if (!(flags & GLOB_NOESCAPE) + && char_array_pos (&dirname, dirlen - 1) == '\\') { /* "pattern\\/". Remove the final backslash if it hasn't been quoted. */ - char *p = (char *) &dirname[dirlen - 1]; - - while (p > dirname && p[-1] == '\\') --p; - if ((&dirname[dirlen] - p) & 1) + size_t p = dirlen - 1; + while (p > 0 && char_array_pos (&dirname, p - 1) == '\\') --p; + if ((dirlen - p) & 1) { - *(char *) &dirname[--dirlen] = '\0'; + /* Since we are shrinking the array, there is no need to + check the function return. */ + dirlen -= 1; + char_array_crop (&dirname, dirlen); flags &= ~(GLOB_NOCHECK | GLOB_NOMAGIC); } } - int val = __glob (dirname, flags | GLOB_MARK, errfunc, pglob); + int val = __glob (char_array_str (&dirname), flags | GLOB_MARK, + errfunc, pglob); if (val == 0) pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK) | (flags & GLOB_MARK)); @@ -608,11 +615,14 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), } } - if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && dirname[0] == '~') + if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) + && char_array_pos (&dirname, 0) == '~') { - if (dirname[1] == '\0' || dirname[1] == '/' - || (!(flags & GLOB_NOESCAPE) && dirname[1] == '\\' - && (dirname[2] == '\0' || dirname[2] == '/'))) + if (char_array_pos (&dirname, 1) == '\0' + || char_array_pos (&dirname, 1) == '/' + || (!(flags & GLOB_NOESCAPE) && char_array_pos (&dirname, 1) == '\\' + && (char_array_pos (&dirname, 2) == '\0' + || char_array_pos (&dirname, 2) == '/'))) { /* Look up home directory. */ char *home_dir = getenv ("HOME"); @@ -663,10 +673,7 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), if (err != ERANGE) break; if (!scratch_buffer_grow (&s)) - { - retval = GLOB_NOSPACE; - goto out; - } + goto err_nospace; } if (err == 0) { @@ -675,10 +682,7 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), } scratch_buffer_free (&s); if (err == 0 && home_dir == NULL) - { - retval = GLOB_NOSPACE; - goto out; - } + goto err_nospace; #endif /* WINDOWS32 */ } if (home_dir == NULL || home_dir[0] == '\0') @@ -697,53 +701,26 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), } } /* Now construct the full directory. */ - if (dirname[1] == '\0') + if (char_array_pos (&dirname, 1) == '\0') { - if (__glibc_unlikely (malloc_dirname)) - free (dirname); - - dirname = home_dir; - dirlen = strlen (dirname); - malloc_dirname = malloc_home_dir; + if (!char_array_set_str (&dirname, home_dir)) + goto err_nospace; + dirlen = char_array_size (&dirname) - 1; } else { - char *newp; - size_t home_len = strlen (home_dir); - int use_alloca = glob_use_alloca (alloca_used, home_len + dirlen); - if (use_alloca) - newp = alloca_account (home_len + dirlen, alloca_used); - else - { - newp = malloc (home_len + dirlen); - if (newp == NULL) - { - if (__glibc_unlikely (malloc_home_dir)) - free (home_dir); - retval = GLOB_NOSPACE; - goto out; - } - } - - mempcpy (mempcpy (newp, home_dir, home_len), - &dirname[1], dirlen); - - if (__glibc_unlikely (malloc_dirname)) - free (dirname); - - dirname = newp; - dirlen += home_len - 1; - malloc_dirname = !use_alloca; - - if (__glibc_unlikely (malloc_home_dir)) - free (home_dir); + /* Replaces '~' by the obtained HOME dir. */ + char_array_erase (&dirname, 0); + if (!char_array_prepend_str (&dirname, home_dir)) + goto err_nospace; } - dirname_modified = 1; + dirname_modified = true; } else { #ifndef WINDOWS32 - char *end_name = strchr (dirname, '/'); + char *dirnamestr = char_array_at (&dirname, 0); + char *end_name = strchr (dirnamestr, '/'); char *user_name; int malloc_user_name = 0; char *unescape = NULL; @@ -752,23 +729,23 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), { if (end_name == NULL) { - unescape = strchr (dirname, '\\'); + unescape = strchr (dirnamestr, '\\'); if (unescape) end_name = strchr (unescape, '\0'); } else - unescape = memchr (dirname, '\\', end_name - dirname); + unescape = memchr (dirnamestr, '\\', end_name - dirnamestr); } if (end_name == NULL) - user_name = dirname + 1; + user_name = dirnamestr + 1; else { char *newp; - if (glob_use_alloca (alloca_used, end_name - dirname)) - newp = alloca_account (end_name - dirname, alloca_used); + if (glob_use_alloca (alloca_used, end_name - dirnamestr)) + newp = alloca_account (end_name - dirnamestr, alloca_used); else { - newp = malloc (end_name - dirname); + newp = malloc (end_name - dirnamestr); if (newp == NULL) { retval = GLOB_NOSPACE; @@ -778,8 +755,8 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), } if (unescape != NULL) { - char *p = mempcpy (newp, dirname + 1, - unescape - dirname - 1); + char *p = mempcpy (newp, dirnamestr + 1, + unescape - dirnamestr - 1); char *q = unescape; while (q != end_name) { @@ -801,8 +778,9 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), *p = '\0'; } else - *((char *) mempcpy (newp, dirname + 1, end_name - dirname - 1)) - = '\0'; + *((char *) mempcpy (newp, dirnamestr + 1, + end_name - dirnamestr - 1)) + = '\0'; user_name = newp; } @@ -835,39 +813,14 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), /* If we found a home directory use this. */ if (p != NULL) { - size_t home_len = strlen (p->pw_dir); - size_t rest_len = end_name == NULL ? 0 : strlen (end_name); - /* dirname contains end_name; we can't free it now. */ - char *prev_dirname = - (__glibc_unlikely (malloc_dirname) ? dirname : NULL); - char *d; - - malloc_dirname = 0; - - if (glob_use_alloca (alloca_used, home_len + rest_len + 1)) - dirname = alloca_account (home_len + rest_len + 1, - alloca_used); - else + if (!char_array_set_str (&dirname, p->pw_dir)) { - dirname = malloc (home_len + rest_len + 1); - if (dirname == NULL) - { - free (prev_dirname); - scratch_buffer_free (&pwtmpbuf); - retval = GLOB_NOSPACE; - goto out; - } - malloc_dirname = 1; + scratch_buffer_free (&pwtmpbuf); + goto err_nospace; } - d = mempcpy (dirname, p->pw_dir, home_len); - if (end_name != NULL) - d = mempcpy (d, end_name, rest_len); - *d = '\0'; - - free (prev_dirname); - dirlen = home_len + rest_len; - dirname_modified = 1; + dirlen = strlen (p->pw_dir); + dirname_modified = true; } else { @@ -908,37 +861,33 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), goto nospace; pglob->gl_pathv = new_gl_pathv; - if (flags & GLOB_MARK && is_dir (dirname, flags, pglob)) + if (flags & GLOB_MARK + && is_dir (char_array_str (&dirname), flags, pglob)) { char *p; pglob->gl_pathv[newcount] = malloc (dirlen + 2); if (pglob->gl_pathv[newcount] == NULL) goto nospace; - p = mempcpy (pglob->gl_pathv[newcount], dirname, dirlen); + p = mempcpy (pglob->gl_pathv[newcount], + char_array_str (&dirname), dirlen); p[0] = '/'; p[1] = '\0'; - if (__glibc_unlikely (malloc_dirname)) - free (dirname); } else { - if (__glibc_unlikely (malloc_dirname)) - pglob->gl_pathv[newcount] = dirname; - else - { - pglob->gl_pathv[newcount] = strdup (dirname); - if (pglob->gl_pathv[newcount] == NULL) - goto nospace; - } + pglob->gl_pathv[newcount] = strdup (char_array_str (&dirname)); + if (pglob->gl_pathv[newcount] == NULL) + goto nospace; } pglob->gl_pathv[++newcount] = NULL; ++pglob->gl_pathc; pglob->gl_flags = flags; - return 0; + goto out; } - meta = __glob_pattern_type (dirname, !(flags & GLOB_NOESCAPE)); + meta = __glob_pattern_type (char_array_str (&dirname), + !(flags & GLOB_NOESCAPE)); /* meta is 1 if correct glob pattern containing metacharacters. If meta has bit (1 << 2) set, it means there was an unterminated [ which we handle the same, using fnmatch. Broken unterminated @@ -951,15 +900,15 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), the pattern in each directory found. */ size_t i; - if (!(flags & GLOB_NOESCAPE) && dirlen > 0 && dirname[dirlen - 1] == '\\') + if (!(flags & GLOB_NOESCAPE) && dirlen > 0 + && char_array_pos (&dirname, dirlen - 1) == '\\') { /* "foo\\/bar". Remove the final backslash from dirname if it has not been quoted. */ - char *p = (char *) &dirname[dirlen - 1]; - - while (p > dirname && p[-1] == '\\') --p; - if ((&dirname[dirlen] - p) & 1) - *(char *) &dirname[--dirlen] = '\0'; + size_t p = dirlen - 1; + while (p > 0 && char_array_pos (&dirname, p - 1) == '\\') --p; + if ((dirlen - p) & 1) + char_array_crop (&dirname, --dirlen); } if (__glibc_unlikely ((flags & GLOB_ALTDIRFUNC) != 0)) @@ -973,7 +922,7 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), dirs.gl_lstat = pglob->gl_lstat; } - status = __glob (dirname, + status = __glob (char_array_str (&dirname), ((flags & (GLOB_ERR | GLOB_NOESCAPE | GLOB_ALTDIRFUNC)) | GLOB_NOSORT | GLOB_ONLYDIR), errfunc, &dirs); @@ -1020,8 +969,7 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), globfree (&dirs); globfree (pglob); pglob->gl_pathc = 0; - retval = GLOB_NOSPACE; - goto out; + goto err_nospace; } } @@ -1043,8 +991,7 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), { nospace2: globfree (&dirs); - retval = GLOB_NOSPACE; - goto out; + goto err_nospace; } new_gl_pathv = realloc (pglob->gl_pathv, @@ -1059,8 +1006,7 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), globfree (&dirs); globfree (pglob); pglob->gl_pathc = 0; - retval = GLOB_NOSPACE; - goto out; + goto err_nospace; } ++pglob->gl_pathc; @@ -1086,7 +1032,7 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), if (meta & GLOBPAT_BACKSLASH) { - char *p = strchr (dirname, '\\'), *q; + char *p = strchr (char_array_str (&dirname), '\\'), *q; /* We need to unescape the dirname string. It is certainly allocated by alloca, as otherwise filename would be NULL or dirname wouldn't contain backslashes. */ @@ -1103,12 +1049,12 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), ++q; } while (*p++ != '\0'); - dirname_modified = 1; + dirname_modified = true; } if (dirname_modified) flags &= ~(GLOB_NOCHECK | GLOB_NOMAGIC); - status = glob_in_dir (filename, dirname, flags, errfunc, pglob, - alloca_used); + status = glob_in_dir (filename, char_array_str (&dirname), flags, + errfunc, pglob, alloca_used); if (status != 0) { if (status == GLOB_NOMATCH && flags != orig_flags @@ -1126,14 +1072,13 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), if (dirlen > 0) { /* Stick the directory on the front of each name. */ - if (prefix_array (dirname, + if (prefix_array (char_array_str (&dirname), &pglob->gl_pathv[old_pathc + pglob->gl_offs], pglob->gl_pathc - old_pathc)) { globfree (pglob); pglob->gl_pathc = 0; - retval = GLOB_NOSPACE; - goto out; + goto err_nospace; } } } @@ -1152,8 +1097,7 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), { globfree (pglob); pglob->gl_pathc = 0; - retval = GLOB_NOSPACE; - goto out; + goto err_nospace; } strcpy (&new[len - 2], "/"); pglob->gl_pathv[i] = new; @@ -1169,10 +1113,13 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), } out: - if (__glibc_unlikely (malloc_dirname)) - free (dirname); + char_array_free (&dirname); return retval; + + err_nospace: + char_array_free (&dirname); + return GLOB_NOSPACE; } #if defined _LIBC && !defined __glob versioned_symbol (libc, __glob, glob, GLIBC_2_27); From patchwork Tue Jan 5 18:58:15 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella Netto X-Patchwork-Id: 41642 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 03A3B393C840; Tue, 5 Jan 2021 18:58:35 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 03A3B393C840 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1609873115; bh=idgZXewE+Y6T8GUE9Z9UY+af7Vjv2kt6CB0vOwDuDQE=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=jslhhOByO37+d0257aOgJ2Oxvd3jLd/D7HKeB+o6fr3Gnrm0+n8skckI5dqTIdyjp KTgevy3vMlcRcYWUafU5u/qLBMujQNouNxIisYQRyyP/71W6vPDDVx7sKavEtKhU2i zaOCfWVjQgNymykGPCrxBY+BCEzKWSYHKFl2foCs= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-qt1-x833.google.com (mail-qt1-x833.google.com [IPv6:2607:f8b0:4864:20::833]) by sourceware.org (Postfix) with ESMTPS id 41C5E393BC39 for ; Tue, 5 Jan 2021 18:58:32 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 41C5E393BC39 Received: by mail-qt1-x833.google.com with SMTP id z3so417922qtw.9 for ; Tue, 05 Jan 2021 10:58:32 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=idgZXewE+Y6T8GUE9Z9UY+af7Vjv2kt6CB0vOwDuDQE=; b=Y+fdEY33pg+/5rRrooXAuE1G0wVZkyaI9QpOm50Go5vEiLko1smftmPjcdQVQ2RAxR jpsKhSSxDWFYCm/rTcRaWJFO8TLwbuejDl7GWSkM+leVWHGpo/SDdIGuEDBn0gnU01BD iFm03kF68PdOJkwwJFmOcqp95SFYjvWLiAQMzK6xPfblwWXMiMLz23w2BMFpUnlkwmqv GnkSRTkTRDrw+yp+LSaLY657wzSM3DDUkdGdBvnmzKsKOIG/einXIKFgwAtgt2flZlWn QGUjK6oeCgkQEKsVGDR3dRj2a4IpPAdPlDr3hi0TtL0yTucqH26AHLdVkj4GzJDpxN4S YN3Q== X-Gm-Message-State: AOAM533/c+roTnSVyY+/5IUocnmqMfSERAVXzTSQDhE+prK++br3lJ5n aKK3nUgvG8chp4aPnDODbUaYHxf6IBuUOg== X-Google-Smtp-Source: ABdhPJxIItdqPSQd1s7sJXyvef0lIsysH/j7qhwYg25JzQgkiOAEuNB+3HBMlqSBaN0qt0NNhloD0w== X-Received: by 2002:ac8:6b86:: with SMTP id z6mr903816qts.26.1609873111619; Tue, 05 Jan 2021 10:58:31 -0800 (PST) Received: from localhost.localdomain ([177.194.48.209]) by smtp.googlemail.com with ESMTPSA id t68sm67792qkd.35.2021.01.05.10.58.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Jan 2021 10:58:31 -0800 (PST) To: libc-alpha@sourceware.org, Paul Eggert , bug-gnulib@gnu.org Subject: [PATCH 3/8] posix: Remove alloca usage for GLOB_BRACE on glob Date: Tue, 5 Jan 2021 15:58:15 -0300 Message-Id: <20210105185820.3796657-4-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210105185820.3796657-1-adhemerval.zanella@linaro.org> References: <20210105185820.3796657-1-adhemerval.zanella@linaro.org> MIME-Version: 1.0 X-Spam-Status: No, score=-13.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Adhemerval Zanella via Libc-alpha From: Adhemerval Zanella Netto Reply-To: Adhemerval Zanella Errors-To: libc-alpha-bounces@sourceware.org Sender: "Libc-alpha" GNU GLOB_BRACE internal implementation constructs a new expression and calls glob recursively. It then requires a possible large temporary buffer place the new pattern. This patch removes the alloca/malloc usage and replaces it with char_array. Checked on x86_64-linux-gnu. --- posix/glob.c | 53 ++++++++++++++++++++++++++++------------------------ 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/posix/glob.c b/posix/glob.c index 8c6e1914c5..41e1aeacad 100644 --- a/posix/glob.c +++ b/posix/glob.c @@ -382,25 +382,23 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), /* Allocate working buffer large enough for our work. Note that we have at least an opening and closing brace. */ size_t firstc; - char *alt_start; const char *p; const char *next; const char *rest; size_t rest_len; - char *onealt; - size_t pattern_len = strlen (pattern) - 1; - int alloca_onealt = glob_use_alloca (alloca_used, pattern_len); - if (alloca_onealt) - onealt = alloca_account (pattern_len, alloca_used); - else - { - onealt = malloc (pattern_len); - if (onealt == NULL) - goto err_nospace; - } + struct char_array onealt; /* We know the prefix for all sub-patterns. */ - alt_start = mempcpy (onealt, pattern, begin - pattern); + ptrdiff_t onealtlen = begin - pattern; + if (!char_array_init_str_size (&onealt, pattern, onealtlen)) + { + if (!(flags & GLOB_APPEND)) + { + pglob->gl_pathc = 0; + pglob->gl_pathv = NULL; + } + goto err_nospace; + } /* Find the first sub-pattern and at the same time find the rest after the closing brace. */ @@ -408,9 +406,7 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), if (next == NULL) { /* It is an invalid expression. */ - illegal_brace: - if (__glibc_unlikely (!alloca_onealt)) - free (onealt); + char_array_free (&onealt); flags &= ~GLOB_BRACE; goto no_brace; } @@ -421,8 +417,12 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), { rest = next_brace_sub (rest + 1, flags); if (rest == NULL) - /* It is an illegal expression. */ - goto illegal_brace; + { + /* It is an illegal expression. */ + char_array_free (&onealt); + flags &= ~GLOB_BRACE; + goto no_brace; + } } /* Please note that we now can be sure the brace expression is well-formed. */ @@ -441,9 +441,16 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), int result; /* Construct the new glob expression. */ - mempcpy (mempcpy (alt_start, p, next - p), rest, rest_len); + ptrdiff_t nextlen = next - p; + if (!char_array_replace_str_pos (&onealt, onealtlen, p, nextlen) + || !char_array_replace_str_pos (&onealt, onealtlen + nextlen, + rest, rest_len)) + { + char_array_free (&onealt); + goto err_nospace; + } - result = __glob (onealt, + result = __glob (char_array_str (&onealt), ((flags & ~(GLOB_NOCHECK | GLOB_NOMAGIC)) | GLOB_APPEND), errfunc, pglob); @@ -451,8 +458,7 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), /* If we got an error, return it. */ if (result && result != GLOB_NOMATCH) { - if (__glibc_unlikely (!alloca_onealt)) - free (onealt); + char_array_free (&onealt); if (!(flags & GLOB_APPEND)) { globfree (pglob); @@ -471,8 +477,7 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), assert (next != NULL); } - if (__glibc_unlikely (!alloca_onealt)) - free (onealt); + char_array_free (&onealt); if (pglob->gl_pathc != firstc) /* We found some entries. */ From patchwork Tue Jan 5 18:58:16 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella Netto X-Patchwork-Id: 41645 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 129C2393C858; Tue, 5 Jan 2021 18:58:37 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 129C2393C858 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1609873117; bh=FMizFL2ZyfDqY8Subj3AWHoI48LSDGN2hqNvtiPxCPE=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=cHR3ICGUyZsTQ+4TOgbZOMPmKOGNBbozPyn3BY4GkqG0LX2mUAEBrVwXj1SDA+x9e aoTmOjnAMURWomm84MMlZzj3tX2QzhSCPozY/C3O95olU48Mrng6JyoiE8zIJiFWX0 +IiAKes6O2WK8nQjtCh84DzrLgDoXfqcu8JNrSD0= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-qk1-x729.google.com (mail-qk1-x729.google.com [IPv6:2607:f8b0:4864:20::729]) by sourceware.org (Postfix) with ESMTPS id E9037384B00F for ; Tue, 5 Jan 2021 18:58:33 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org E9037384B00F Received: by mail-qk1-x729.google.com with SMTP id v126so268114qkd.11 for ; Tue, 05 Jan 2021 10:58:33 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=FMizFL2ZyfDqY8Subj3AWHoI48LSDGN2hqNvtiPxCPE=; b=f+KgvkjIne+6oyK5hN/Et5Mnky2awhEUcTbYjx+qZkJuuOSHclMxF0q0UaVWtuNek3 9jGWVkzNwpsiL+weEaDh6nyJvGXzgJaiPwj3UDVBzS9vQ7qo7kYKRE9lqPS+hKZLOweV wttHEbmhBHHffwLsJrpYgvRlVBcd1zhiqZNEJNLcv6RuEiqOs+PZdPEKKw76uAku1Rc5 Ya24OkDRN4ti6tFXP04336pfavLUztRnpLUQdFelTesfAPC5/NMRh0wKSH8yI643JL/Y 1/8fuMwEDiXoF9fIyBBZMTTgiSvd+JTQc7xxuDZTUj/fVVERjCC6wfSgY9nksP4TOHSJ fDcQ== X-Gm-Message-State: AOAM532kvRb4QwqPkjQYVY7o9jGToKas2fQQ+XmPBJqZWkDJDRUUPPDj AA1gxrq88TlCuw5UPLJxtyLdGDG+FiHSoQ== X-Google-Smtp-Source: ABdhPJy6pSH7pujLlSTb0WaxCwLxB7eZqbE/JHnTl+1vitE93ts7R1etYOhaNnbC2nan2TXL4ysmtA== X-Received: by 2002:a37:c0d:: with SMTP id 13mr877628qkm.275.1609873113433; Tue, 05 Jan 2021 10:58:33 -0800 (PST) Received: from localhost.localdomain ([177.194.48.209]) by smtp.googlemail.com with ESMTPSA id t68sm67792qkd.35.2021.01.05.10.58.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Jan 2021 10:58:33 -0800 (PST) To: libc-alpha@sourceware.org, Paul Eggert , bug-gnulib@gnu.org Subject: [PATCH 4/8] posix: Remove alloca usage on glob dirname Date: Tue, 5 Jan 2021 15:58:16 -0300 Message-Id: <20210105185820.3796657-5-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210105185820.3796657-1-adhemerval.zanella@linaro.org> References: <20210105185820.3796657-1-adhemerval.zanella@linaro.org> MIME-Version: 1.0 X-Spam-Status: No, score=-13.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Adhemerval Zanella via Libc-alpha From: Adhemerval Zanella Netto Reply-To: Adhemerval Zanella Errors-To: libc-alpha-bounces@sourceware.org Sender: "Libc-alpha" This patch replaces the alloca/malloc usage for dirname creation by the char_array struct. Checked on x86_64-linux-gnu. --- posix/glob.c | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/posix/glob.c b/posix/glob.c index 41e1aeacad..d734ca977c 100644 --- a/posix/glob.c +++ b/posix/glob.c @@ -1212,7 +1212,6 @@ glob_in_dir (const char *pattern, const char *directory, int flags, int (*errfunc) (const char *, int), glob_t *pglob, size_t alloca_used) { - size_t dirlen = strlen (directory); void *stream = NULL; # define GLOBNAMES_MEMBERS(nnames) \ struct globnames *next; size_t count; char *name[nnames]; @@ -1244,32 +1243,23 @@ glob_in_dir (const char *pattern, const char *directory, int flags, } else if (meta == GLOBPAT_NONE) { - size_t patlen = strlen (pattern); - size_t fullsize; - bool alloca_fullname - = (! size_add_wrapv (dirlen + 1, patlen + 1, &fullsize) - && glob_use_alloca (alloca_used, fullsize)); - char *fullname; - if (alloca_fullname) - fullname = alloca_account (fullsize, alloca_used); - else + struct char_array fullname; + + if (!char_array_init_str (&fullname, directory) + || !char_array_append_str (&fullname, "/") + || !char_array_append_str (&fullname, pattern)) { - fullname = malloc (fullsize); - if (fullname == NULL) - return GLOB_NOSPACE; + char_array_free (&fullname); + return GLOB_NOSPACE; } - mempcpy (mempcpy (mempcpy (fullname, directory, dirlen), - "/", 1), - pattern, patlen + 1); - if (glob_lstat (pglob, flags, fullname) == 0 + if (glob_lstat (pglob, flags, char_array_str (&fullname)) == 0 || errno == EOVERFLOW) /* We found this file to be existing. Now tell the rest of the function to copy this name into the result. */ flags |= GLOB_NOCHECK; - if (__glibc_unlikely (!alloca_fullname)) - free (fullname); + char_array_free (&fullname); } else { From patchwork Tue Jan 5 18:58:17 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella Netto X-Patchwork-Id: 41646 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 98ADB393C848; Tue, 5 Jan 2021 18:58:38 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 98ADB393C848 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1609873118; bh=y/wyyQqphtX9kIwPh/lIMreOMEsFUm9C+qNGb3SHEa8=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=qmqD9LOl9RMbIENMnx6D9liMm3Ty0imXZMPhJMBOV7kOgAFDu84w3gbLRJE+2Vgqa s5m+B9+Cy2L1d3xs6ySP2lm4Aiy/kQX/pSQXTbFBui8J+T5GAGzUsdp4TeGVDeYBcB DXG0kBlSiffb6X/J1Y1SWcNyd/z0zjubreWowl08= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-qt1-x82a.google.com (mail-qt1-x82a.google.com [IPv6:2607:f8b0:4864:20::82a]) by sourceware.org (Postfix) with ESMTPS id CE6AD389246C for ; Tue, 5 Jan 2021 18:58:35 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org CE6AD389246C Received: by mail-qt1-x82a.google.com with SMTP id j26so422820qtq.8 for ; Tue, 05 Jan 2021 10:58:35 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=y/wyyQqphtX9kIwPh/lIMreOMEsFUm9C+qNGb3SHEa8=; b=DS6MNlqOVRmfrR0UUxwwnaRQETXHYL4JM3vna16dv9oGjpih0/FXOX0Xd/xPdrSRMq uItzwodD+ExzjpHqHQ1f1D4B13dE6lFVjMEXYRq7FCTFh8PFY/Sj0uGOI7QpBAlwxfRt sG2QJ12pGD0GNlxNDCkdqC3G221vQZ3gZIqPAqMAxKzNAEjAaTTB9IPaCdIq1sMBAwCw p/VSuPsH1b1POtV9E2lP9KjaQ7TYBxdDPe04LwHSF9cNTdxxI3YmVjW4KDJ9xIgvMjEw uRbm2NBkhdzR5Dqi112TNJjupGnpwkzIDQZ63Kh15zSa+33XF5RTRtmKrmESh7Q+zxif tahQ== X-Gm-Message-State: AOAM533mXUyEotRxeJrc1GJ+jNR7Wawf0CfvMUbb014n6S8S7aSmmy8q F/oQt0WSTUccnjmAzpBIccGX/1yRIdHguA== X-Google-Smtp-Source: ABdhPJyKIvq/Il/95Z83WYcFXvY4RlUnAYJ/tEZ8giEGU6RZFg+hYk3mLu4x/9ac6foNU9ykbTroXQ== X-Received: by 2002:ac8:2af9:: with SMTP id c54mr881560qta.362.1609873115148; Tue, 05 Jan 2021 10:58:35 -0800 (PST) Received: from localhost.localdomain ([177.194.48.209]) by smtp.googlemail.com with ESMTPSA id t68sm67792qkd.35.2021.01.05.10.58.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Jan 2021 10:58:34 -0800 (PST) To: libc-alpha@sourceware.org, Paul Eggert , bug-gnulib@gnu.org Subject: [PATCH 5/8] posix: Use dynarray for globname in glob Date: Tue, 5 Jan 2021 15:58:17 -0300 Message-Id: <20210105185820.3796657-6-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210105185820.3796657-1-adhemerval.zanella@linaro.org> References: <20210105185820.3796657-1-adhemerval.zanella@linaro.org> MIME-Version: 1.0 X-Spam-Status: No, score=-13.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Adhemerval Zanella via Libc-alpha From: Adhemerval Zanella Netto Reply-To: Adhemerval Zanella Errors-To: libc-alpha-bounces@sourceware.org Sender: "Libc-alpha" This patch uses dynarray at glob internal glob_in_dir function to manage the various matched patterns. It simplify and removes all the boilerplate buffer managements required. It also removes the glob_use_alloca, since it is not used anymore. Checked on x86_64-linux-gnu. --- posix/glob.c | 126 +++++++++++++++------------------------------------ 1 file changed, 37 insertions(+), 89 deletions(-) diff --git a/posix/glob.c b/posix/glob.c index d734ca977c..d199204931 100644 --- a/posix/glob.c +++ b/posix/glob.c @@ -1203,6 +1203,21 @@ prefix_array (const char *dirname, char **array, size_t n) return 0; } +struct globnames_result +{ + char **names; + size_t length; +}; + +/* Create a dynamic array for C string representing the glob name found. */ +#define DYNARRAY_STRUCT globnames_array +#define DYNARRAY_ELEMENT_FREE(ptr) free (*ptr) +#define DYNARRAY_ELEMENT char * +#define DYNARRAY_PREFIX globnames_array_ +#define DYNARRAY_FINAL_TYPE struct globnames_result +#define DYNARRAY_INITIAL_SIZE 64 +#include + /* Like 'glob', but PATTERN is a final pathname component, and matches are searched for in DIRECTORY. The GLOB_NOSORT bit in FLAGS is ignored. No sorting is ever done. @@ -1213,25 +1228,13 @@ glob_in_dir (const char *pattern, const char *directory, int flags, glob_t *pglob, size_t alloca_used) { void *stream = NULL; -# define GLOBNAMES_MEMBERS(nnames) \ - struct globnames *next; size_t count; char *name[nnames]; - struct globnames { GLOBNAMES_MEMBERS (FLEXIBLE_ARRAY_MEMBER) }; - struct { GLOBNAMES_MEMBERS (64) } init_names_buf; - struct globnames *init_names = (struct globnames *) &init_names_buf; - struct globnames *names = init_names; - struct globnames *names_alloca = init_names; + struct globnames_array globnames; size_t nfound = 0; - size_t cur = 0; int meta; int save; int result; - alloca_used += sizeof init_names_buf; - - init_names->next = NULL; - init_names->count = ((sizeof init_names_buf - - offsetof (struct globnames, name)) - / sizeof init_names->name[0]); + globnames_array_init (&globnames); meta = __glob_pattern_type (pattern, !(flags & GLOB_NOESCAPE)); if (meta == GLOBPAT_NONE && (flags & (GLOB_NOCHECK|GLOB_NOMAGIC))) @@ -1308,34 +1311,10 @@ glob_in_dir (const char *pattern, const char *directory, int flags, if (fnmatch (pattern, d.name, fnm_flags) == 0) { - if (cur == names->count) - { - struct globnames *newnames; - size_t count = names->count * 2; - size_t nameoff = offsetof (struct globnames, name); - size_t size = FLEXSIZEOF (struct globnames, name, - count * sizeof (char *)); - if ((SIZE_MAX - nameoff) / 2 / sizeof (char *) - < names->count) - goto memory_error; - if (glob_use_alloca (alloca_used, size)) - newnames = names_alloca - = alloca_account (size, alloca_used); - else if ((newnames = malloc (size)) - == NULL) - goto memory_error; - newnames->count = count; - newnames->next = names; - names = newnames; - cur = 0; - } - names->name[cur] = strdup (d.name); - if (names->name[cur] == NULL) - goto memory_error; - ++cur; - ++nfound; - if (SIZE_MAX - pglob->gl_offs <= nfound) + globnames_array_add (&globnames, strdup (d.name)); + if (globnames_array_has_failed (&globnames)) goto memory_error; + nfound++; } } } @@ -1345,10 +1324,13 @@ glob_in_dir (const char *pattern, const char *directory, int flags, { size_t len = strlen (pattern); nfound = 1; - names->name[cur] = malloc (len + 1); - if (names->name[cur] == NULL) + char *newp = malloc (len + 1); + if (newp == NULL) goto memory_error; - *((char *) mempcpy (names->name[cur++], pattern, len)) = '\0'; + *((char *) mempcpy (newp, pattern, len)) = '\0'; + globnames_array_add (&globnames, newp); + if (globnames_array_has_failed (&globnames)) + goto memory_error; } result = GLOB_NOMATCH; @@ -1369,59 +1351,25 @@ glob_in_dir (const char *pattern, const char *directory, int flags, if (new_gl_pathv == NULL) { memory_error: - while (1) - { - struct globnames *old = names; - for (size_t i = 0; i < cur; ++i) - free (names->name[i]); - names = names->next; - /* NB: we will not leak memory here if we exit without - freeing the current block assigned to OLD. At least - the very first block is always allocated on the stack - and this is the block assigned to OLD here. */ - if (names == NULL) - { - assert (old == init_names); - break; - } - cur = names->count; - if (old == names_alloca) - names_alloca = names; - else - free (old); - } + globnames_array_free (&globnames); result = GLOB_NOSPACE; } else { - while (1) + struct globnames_result ret = { .names = 0, .length = -1 }; + if (!globnames_array_finalize (&globnames, &ret)) + result = GLOB_NOSPACE; + else { - struct globnames *old = names; - for (size_t i = 0; i < cur; ++i) + for (size_t i = 0; i < ret.length; ++i) new_gl_pathv[pglob->gl_offs + pglob->gl_pathc++] - = names->name[i]; - names = names->next; - /* NB: we will not leak memory here if we exit without - freeing the current block assigned to OLD. At least - the very first block is always allocated on the stack - and this is the block assigned to OLD here. */ - if (names == NULL) - { - assert (old == init_names); - break; - } - cur = names->count; - if (old == names_alloca) - names_alloca = names; - else - free (old); + = ret.names[i]; + pglob->gl_pathv = new_gl_pathv; + pglob->gl_pathv[pglob->gl_offs + pglob->gl_pathc] = NULL; + pglob->gl_flags = flags; } - pglob->gl_pathv = new_gl_pathv; - - pglob->gl_pathv[pglob->gl_offs + pglob->gl_pathc] = NULL; - - pglob->gl_flags = flags; + free (ret.names); } } From patchwork Tue Jan 5 18:58:18 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella Netto X-Patchwork-Id: 41647 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 2A1EA393C84F; Tue, 5 Jan 2021 18:58:40 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 2A1EA393C84F DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1609873120; bh=g6XP+QuvjzYlCI5Y+NQhTpJd2+1388u5KtirBCNxRy4=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=pMSEoK+n25ktkHJHEcIyyZ7TENtzPKiP8iQQE7p/nBYWBi7goO3G9vKDUMaPBS19H Iv5o1VqrN9qeu0qN30yGMyqEHpCKTjBM8Frb2jNVijdFl7wcvwZU+7W0xaCa2bWy3u V5TwOi6x1nRQ3Ihny7tY/xEdNoRp7pMlyUQefbb8= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-qk1-x72f.google.com (mail-qk1-x72f.google.com [IPv6:2607:f8b0:4864:20::72f]) by sourceware.org (Postfix) with ESMTPS id 85004393C85C for ; Tue, 5 Jan 2021 18:58:37 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 85004393C85C Received: by mail-qk1-x72f.google.com with SMTP id b64so258232qkc.12 for ; Tue, 05 Jan 2021 10:58:37 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=g6XP+QuvjzYlCI5Y+NQhTpJd2+1388u5KtirBCNxRy4=; b=aYlg7RTO1sSC1g/rRzQTOhnWORmNQUjYMWRaK3v7adjEpptIA4+QHJkKx8NX5CesDF D3n50YIMQPNiEaGSQckQLmmRbRCUvkm+hSSEvSjjsEB8RWzrzkHxO0eDJGVMyMLMOoeq ECiTSn9Mj4GGczykc+o7WoGQghdbwMycR0JOXQkxvpJz8a277jTNTCqF38s+THgI2UaA silvC4g1tyELn0mGBT5PKqIYfWB8+WefrYwMBkJ7k/ghojQxbZ1RWleBVGlsLOUMTHwy GMiMfb0gECOl9WWyXA82BgefWWg2UoRL4mZrx9uHUmEDTPaINq39NxCAUfi14Ukbrz2m qsMw== X-Gm-Message-State: AOAM5325sUK9E+s7hXw9cGk3sRecUg1r2YMiNKzbo5G74OWQVS/aHLCn aM+Itbs5dnGyCN8Mb9D6IaeZSPVimeLNTA== X-Google-Smtp-Source: ABdhPJzJWZcp/OBrvvmB5bnEP+e+fsn8z807BstZCuHYTsMCRLZ+YO/QIvdH1dz+syYbtjRsvyuEqQ== X-Received: by 2002:a37:896:: with SMTP id 144mr955665qki.96.1609873116880; Tue, 05 Jan 2021 10:58:36 -0800 (PST) Received: from localhost.localdomain ([177.194.48.209]) by smtp.googlemail.com with ESMTPSA id t68sm67792qkd.35.2021.01.05.10.58.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Jan 2021 10:58:36 -0800 (PST) To: libc-alpha@sourceware.org, Paul Eggert , bug-gnulib@gnu.org Subject: [PATCH 6/8] posix: Remove alloca usage on glob user_name Date: Tue, 5 Jan 2021 15:58:18 -0300 Message-Id: <20210105185820.3796657-7-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210105185820.3796657-1-adhemerval.zanella@linaro.org> References: <20210105185820.3796657-1-adhemerval.zanella@linaro.org> MIME-Version: 1.0 X-Spam-Status: No, score=-13.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Adhemerval Zanella via Libc-alpha From: Adhemerval Zanella Netto Reply-To: Adhemerval Zanella Errors-To: libc-alpha-bounces@sourceware.org Sender: "Libc-alpha" This patch uses dynarray at glob internal user name manipulation for GLOB_TILDE. It simplifies it and removes all the boilerplate buffer managements required. It also removes the glob_use_alloca, since it is not used anymore. Checked on x86_64-linux-gnu. --- posix/glob.c | 86 ++++++++++++++++------------------------------------ 1 file changed, 26 insertions(+), 60 deletions(-) diff --git a/posix/glob.c b/posix/glob.c index d199204931..c126b4501d 100644 --- a/posix/glob.c +++ b/posix/glob.c @@ -42,13 +42,13 @@ #ifndef WINDOWS32 # include +# include #endif #include #include #include #include -#include #ifdef _LIBC # undef strdup @@ -215,29 +215,6 @@ glob_lstat (glob_t *pglob, int flags, const char *fullname) : LSTAT64 (fullname, &ust.st64)); } -/* Set *R = A + B. Return true if the answer is mathematically - incorrect due to overflow; in this case, *R is the low order - bits of the correct answer. */ - -static bool -size_add_wrapv (size_t a, size_t b, size_t *r) -{ -#if 7 <= __GNUC__ && !defined __ICC - return __builtin_add_overflow (a, b, r); -#else - *r = a + b; - return *r < a; -#endif -} - -static bool -glob_use_alloca (size_t alloca_used, size_t len) -{ - size_t size; - return (!size_add_wrapv (alloca_used, len, &size) - && __libc_use_alloca (size)); -} - static int glob_in_dir (const char *pattern, const char *directory, int flags, int (*errfunc) (const char *, int), glob_t *pglob, size_t alloca_used); @@ -724,11 +701,10 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), else { #ifndef WINDOWS32 - char *dirnamestr = char_array_at (&dirname, 0); - char *end_name = strchr (dirnamestr, '/'); - char *user_name; - int malloc_user_name = 0; - char *unescape = NULL; + const char *dirnamestr = char_array_str (&dirname); + const char *end_name = strchr (dirnamestr, '/'); + struct char_array user_name; + const char *unescape = NULL; if (!(flags & GLOB_NOESCAPE)) { @@ -742,27 +718,19 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), unescape = memchr (dirnamestr, '\\', end_name - dirnamestr); } if (end_name == NULL) - user_name = dirnamestr + 1; + { + if (!char_array_init_str (&user_name, dirnamestr + 1)) + goto err_nospace; + } else { - char *newp; - if (glob_use_alloca (alloca_used, end_name - dirnamestr)) - newp = alloca_account (end_name - dirnamestr, alloca_used); - else - { - newp = malloc (end_name - dirnamestr); - if (newp == NULL) - { - retval = GLOB_NOSPACE; - goto out; - } - malloc_user_name = 1; - } if (unescape != NULL) { - char *p = mempcpy (newp, dirnamestr + 1, - unescape - dirnamestr - 1); - char *q = unescape; + ptrdiff_t name_len = unescape - dirnamestr - 1; + if (!char_array_init_str_size (&user_name, dirnamestr + 1, + name_len)) + goto err_nospace; + const char *q = unescape; while (q != end_name) { if (*q == '\\') @@ -773,20 +741,21 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), but "~fo\\o\\/" unescape to user_name "foo". */ if (filename == NULL) - *p++ = '\\'; + char_array_append_char (&user_name, '\\'); break; } ++q; } - *p++ = *q++; + char_array_append_char (&user_name, *q++); } - *p = '\0'; } else - *((char *) mempcpy (newp, dirnamestr + 1, - end_name - dirnamestr - 1)) - = '\0'; - user_name = newp; + { + ptrdiff_t name_len = end_name - dirnamestr - 1; + if (!char_array_init_str_size (&user_name, dirnamestr + 1, + name_len)) + goto err_nospace; + } } /* Look up specific user's home directory. */ @@ -798,7 +767,7 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), # if defined HAVE_GETPWNAM_R || defined _LIBC struct passwd pwbuf; - while (getpwnam_r (user_name, &pwbuf, + while (getpwnam_r (char_array_str (&user_name), &pwbuf, pwtmpbuf.data, pwtmpbuf.length, &p) == ERANGE) { @@ -809,11 +778,10 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), } } # else - p = getpwnam (user_name); + p = getpwnam (char_array_str (&user_name)); # endif - if (__glibc_unlikely (malloc_user_name)) - free (user_name); + char_array_free (&user_name); /* If we found a home directory use this. */ if (p != NULL) @@ -1038,9 +1006,7 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), if (meta & GLOBPAT_BACKSLASH) { char *p = strchr (char_array_str (&dirname), '\\'), *q; - /* We need to unescape the dirname string. It is certainly - allocated by alloca, as otherwise filename would be NULL - or dirname wouldn't contain backslashes. */ + /* We need to unescape the dirname string. */ q = p; do { From patchwork Tue Jan 5 18:58:19 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella Netto X-Patchwork-Id: 41648 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 4CFF9393C852; Tue, 5 Jan 2021 18:58:42 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 4CFF9393C852 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1609873122; bh=H+N/s2PkRpLKCj26zNT/jQIAlrfNWHt8dlvp0LQion0=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=S2kWWfFzaEI+f4xw9npKCmJx6dUkR9JgPWKD5AMuWc/MR1Owd+fsExJxfZzNnlQvQ Rnh9FWsYIH8azW++LgvUs92hyMhVLubcWor6iXpY21WYFDGM2zAWsSHwKQVtwPNm75 c+drr0ImYfp8fDeRMDgcP4whv5ffx/jgrkZCgoXE= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-qk1-x735.google.com (mail-qk1-x735.google.com [IPv6:2607:f8b0:4864:20::735]) by sourceware.org (Postfix) with ESMTPS id 3389A393C84D for ; Tue, 5 Jan 2021 18:58:39 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 3389A393C84D Received: by mail-qk1-x735.google.com with SMTP id n142so334965qkn.2 for ; Tue, 05 Jan 2021 10:58:39 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=H+N/s2PkRpLKCj26zNT/jQIAlrfNWHt8dlvp0LQion0=; b=tQHRXxV5NY2QX82C/FL8YAf4qKx0VZkAeXqL/6zD4mTwYubEu6Wkoj3jG4Snbr/bOi +guZ2Zyy1LYvsEWGOoYlJ5/U7dBlVcscQFE28kvO+gnBBteiIavCcbnQ7ssf5DtakRfQ ZmSlRmbnaYlFPgv7Emw/zo6b7UnICxxRF+flWE5LLBZMRYuDQlTNl42wKos1gJoPbE6R TOLjVXFL4sC3UqYI5WxxbEmI1GUPPL0fzzYoMGHh5R1CMtOpXXYiXQGuo2xElWS1M5aQ Jf0igO2hXmXJVmc+bH/jiD50NFxRPVySAnojOb/psR9ahAyOD0Yh/NLldCOjuiMl8Gvl ehDA== X-Gm-Message-State: AOAM532nefrb9mENQ5krhfL2KoibnBfuzFLntPgWfMdXX9VWw0x6MYWj IV2gUf6EiXr37c1a7OI/0co/ru0exnHXtA== X-Google-Smtp-Source: ABdhPJxU+M0y1e3MPU28aUEbqP6V3jGJNV3KxD80kasWodOZDZ7aQwWJBpLeXzFI0HR0xemJsrF8Bw== X-Received: by 2002:a37:6c1:: with SMTP id 184mr862308qkg.381.1609873118586; Tue, 05 Jan 2021 10:58:38 -0800 (PST) Received: from localhost.localdomain ([177.194.48.209]) by smtp.googlemail.com with ESMTPSA id t68sm67792qkd.35.2021.01.05.10.58.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Jan 2021 10:58:38 -0800 (PST) To: libc-alpha@sourceware.org, Paul Eggert , bug-gnulib@gnu.org Subject: [PATCH 7/8] posix: Use char_array for home_dir in glob Date: Tue, 5 Jan 2021 15:58:19 -0300 Message-Id: <20210105185820.3796657-8-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210105185820.3796657-1-adhemerval.zanella@linaro.org> References: <20210105185820.3796657-1-adhemerval.zanella@linaro.org> MIME-Version: 1.0 X-Spam-Status: No, score=-13.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Adhemerval Zanella via Libc-alpha From: Adhemerval Zanella Netto Reply-To: Adhemerval Zanella Errors-To: libc-alpha-bounces@sourceware.org Sender: "Libc-alpha" This patch uses dynarray at glob internal home directory ame manipulation for GLOB_TILDE. It simplifies it and removes all the boilerplate buffer managements required. Checked x86_64-linux-gnu. --- posix/glob.c | 69 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 27 deletions(-) diff --git a/posix/glob.c b/posix/glob.c index c126b4501d..b6727ee884 100644 --- a/posix/glob.c +++ b/posix/glob.c @@ -606,10 +606,15 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), && (char_array_pos (&dirname, 2) == '\0' || char_array_pos (&dirname, 2) == '/'))) { + struct char_array home_dir; + + const char *home_env = getenv ("HOME"); + home_env = home_env == NULL ? "" : home_env; + if (!char_array_init_str (&home_dir, home_env)) + goto err_nospace; + + if (char_array_is_empty (&home_dir)) /* Look up home directory. */ - char *home_dir = getenv ("HOME"); - int malloc_home_dir = 0; - if (home_dir == NULL || home_dir[0] == '\0') { #ifdef WINDOWS32 /* Windows NT defines HOMEDRIVE and HOMEPATH. But give @@ -619,16 +624,21 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), if (home_drive != NULL && home_path != NULL) { - size_t home_drive_len = strlen (home_drive); - size_t home_path_len = strlen (home_path); - char *mem = alloca (home_drive_len + home_path_len + 1); - - memcpy (mem, home_drive, home_drive_len); - memcpy (mem + home_drive_len, home_path, home_path_len + 1); - home_dir = mem; + if (!char_array_set_str (&home_dir, home_drive) + || !char_array_append_str (&home_dir, home_path)) + { + char_array_free (&home_dir); + goto err_nospace; + } } else - home_dir = "c:/users/default"; /* poor default */ + { + if (!char_array_set_str (&home_dir, "c:/users/default")) + { + char_array_free (&home_dir); + goto err_nospace; + } + } #else int err; struct passwd *p; @@ -657,44 +667,49 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), if (!scratch_buffer_grow (&s)) goto err_nospace; } - if (err == 0) - { - home_dir = strdup (p->pw_dir); - malloc_home_dir = 1; - } + if (err == 0 && !char_array_set_str (&home_dir, p->pw_dir)) + err = 1; scratch_buffer_free (&s); - if (err == 0 && home_dir == NULL) - goto err_nospace; + if (err == 0) + goto err_nospace; #endif /* WINDOWS32 */ } - if (home_dir == NULL || home_dir[0] == '\0') + if (char_array_is_empty (&home_dir)) { - if (__glibc_unlikely (malloc_home_dir)) - free (home_dir); if (flags & GLOB_TILDE_CHECK) { + char_array_free (&home_dir); retval = GLOB_NOMATCH; goto out; } else { - home_dir = (char *) "~"; /* No luck. */ - malloc_home_dir = 0; + if (!char_array_set_str (&home_dir, "~")) + { + char_array_free (&home_dir); + goto err_nospace; + } } } /* Now construct the full directory. */ + bool e = true; if (char_array_pos (&dirname, 1) == '\0') { - if (!char_array_set_str (&dirname, home_dir)) - goto err_nospace; + e = char_array_set_str (&dirname, char_array_str (&home_dir)); dirlen = char_array_size (&dirname) - 1; } else { /* Replaces '~' by the obtained HOME dir. */ char_array_erase (&dirname, 0); - if (!char_array_prepend_str (&dirname, home_dir)) - goto err_nospace; + e = char_array_prepend_str (&dirname, + char_array_str (&home_dir)); + } + if (e == false) + { + char_array_free (&dirname); + char_array_free (&home_dir); + goto err_nospace; } dirname_modified = true; } From patchwork Tue Jan 5 18:58:20 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella Netto X-Patchwork-Id: 41649 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 609ED393C863; Tue, 5 Jan 2021 18:58:44 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 609ED393C863 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1609873124; bh=B6ZrpSlZvx9vfcNH+7mP1vKuPEslZb8xuWsu4QeEy9k=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=tAzH413XFnwImm+JaO2oc+Qb/58zGCwEjeBeuN299gkjvYP5VLDbUpRF3dnqvgz8L kYoLJsBH4CacDtZeQsLqWfG4wE1iiX54mldeQfeIh5oGWXEsIppa2Y4LSj4h/CXfV0 W2BkNstm7cfFORVDlkTp+ul5cszqxehDKY6tOa+Y= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-qv1-xf2d.google.com (mail-qv1-xf2d.google.com [IPv6:2607:f8b0:4864:20::f2d]) by sourceware.org (Postfix) with ESMTPS id 10211393C84D for ; Tue, 5 Jan 2021 18:58:41 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 10211393C84D Received: by mail-qv1-xf2d.google.com with SMTP id az16so142160qvb.5 for ; Tue, 05 Jan 2021 10:58:41 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=B6ZrpSlZvx9vfcNH+7mP1vKuPEslZb8xuWsu4QeEy9k=; b=r179nuCjec6iDq6+nP/1oy0TA+CqCMaAU/3P8UNSxz4nS75cT73l8DYTXCizEo7rea 6E8XSTxHure9bP3cCUNFm/R0Slp/tqkg6SyzBLnMAAJNhK5SJ7MKhsn1SucQ9yS+CJ+9 eNZs8CS8NjhOvO3edN4FzyZo72l2HIPIL9ChYiSmuflebAFfU60tFh9OKhxYusndqYNX 2gM4HelH0qdCU5zseJ1SqnUsJAXcVoTQr7ywhpOE/22tV4gYpdbowPIPBVeDOrSF4+mN 5hXFRDJDERr4KVhmu0wj77KOMkDkqEZ1SGn2+0FIa2qbbQc2DLyrtya382BhdOmCiqNG zocQ== X-Gm-Message-State: AOAM531d+1aHcHi6DgiIXUlcWTa6Qy2Jci4QRXRqTFiIcmsNBACrBthl A5/0Skwks52CrZBBX5PIxb8Tq/T3Q5oJqA== X-Google-Smtp-Source: ABdhPJwJZwn+B2lFDHcLK5tWC6NXbDlPyjg2Z8ueoe11i5lXdK69gcd2uxKNqVwSzrL9//0Pc6WGyA== X-Received: by 2002:ad4:5762:: with SMTP id r2mr550199qvx.45.1609873120265; Tue, 05 Jan 2021 10:58:40 -0800 (PST) Received: from localhost.localdomain ([177.194.48.209]) by smtp.googlemail.com with ESMTPSA id t68sm67792qkd.35.2021.01.05.10.58.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Jan 2021 10:58:39 -0800 (PST) To: libc-alpha@sourceware.org, Paul Eggert , bug-gnulib@gnu.org Subject: [PATCH 8/8] posix: Remove all alloca usage in glob Date: Tue, 5 Jan 2021 15:58:20 -0300 Message-Id: <20210105185820.3796657-9-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210105185820.3796657-1-adhemerval.zanella@linaro.org> References: <20210105185820.3796657-1-adhemerval.zanella@linaro.org> MIME-Version: 1.0 X-Spam-Status: No, score=-13.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Adhemerval Zanella via Libc-alpha From: Adhemerval Zanella Netto Reply-To: Adhemerval Zanella Errors-To: libc-alpha-bounces@sourceware.org Sender: "Libc-alpha" With alloca usage removal from glob this patch wraps it up by removing all the alloca defines and macros usage. Checked on x86_64-linux-gnu. --- posix/glob.c | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/posix/glob.c b/posix/glob.c index b6727ee884..c7a89a5298 100644 --- a/posix/glob.c +++ b/posix/glob.c @@ -42,7 +42,6 @@ #ifndef WINDOWS32 # include -# include #endif #include @@ -74,7 +73,6 @@ # define __fxstatat64(_, d, f, st, flag) fstatat (d, f, st, flag) # define struct_stat64 struct stat # ifndef __MVS__ -# define __alloca alloca # endif # define __readdir readdir # define COMPILE_GLOB64 @@ -184,12 +182,6 @@ convert_dirent64 (const struct dirent64 *source) # ifdef GNULIB_defined_closedir # undef closedir # endif - -/* Just use malloc. */ -# define __libc_use_alloca(n) false -# define alloca_account(len, avar) ((void) (len), (void) (avar), (void *) 0) -# define extend_alloca_account(buf, len, newlen, avar) \ - ((void) (buf), (void) (len), (void) (newlen), (void) (avar), (void *) 0) #endif static int @@ -217,7 +209,7 @@ glob_lstat (glob_t *pglob, int flags, const char *fullname) static int glob_in_dir (const char *pattern, const char *directory, int flags, int (*errfunc) (const char *, int), - glob_t *pglob, size_t alloca_used); + glob_t *pglob); static int prefix_array (const char *prefix, char **array, size_t n) __THROWNL; static int collated_compare (const void *, const void *) __THROWNL; @@ -282,7 +274,6 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), int meta; glob_t dirs; int retval = 0; - size_t alloca_used = 0; struct char_array dirname; bool dirname_modified; @@ -530,11 +521,13 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), char *drive_spec; ++dirlen; - drive_spec = __alloca (dirlen + 1); + drive_spec = malloca (dirlen + 1); *((char *) mempcpy (drive_spec, pattern, dirlen)) = '\0'; /* For now, disallow wildcards in the drive spec, to prevent infinite recursion in glob. */ - if (__glob_pattern_p (drive_spec, !(flags & GLOB_NOESCAPE))) + int r = __glob_pattern_p (drive_spec, !(flags & GLOB_NOESCAPE)); + free (drive_spec); + if (r != 0) { retval = GLOB_NOMATCH; goto out; @@ -935,7 +928,7 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), status = glob_in_dir (filename, dirs.gl_pathv[i], ((flags | GLOB_APPEND) & ~(GLOB_NOCHECK | GLOB_NOMAGIC)), - errfunc, pglob, alloca_used); + errfunc, pglob); if (status == GLOB_NOMATCH) /* No matches in this directory. Try the next. */ continue; @@ -1040,7 +1033,7 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), if (dirname_modified) flags &= ~(GLOB_NOCHECK | GLOB_NOMAGIC); status = glob_in_dir (filename, char_array_str (&dirname), flags, - errfunc, pglob, alloca_used); + errfunc, pglob); if (status != 0) { if (status == GLOB_NOMATCH && flags != orig_flags @@ -1206,7 +1199,7 @@ struct globnames_result static int glob_in_dir (const char *pattern, const char *directory, int flags, int (*errfunc) (const char *, int), - glob_t *pglob, size_t alloca_used) + glob_t *pglob) { void *stream = NULL; struct globnames_array globnames;