From patchwork Thu Jun 15 10:48:34 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 1795362 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=sourceware.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=sourceware.org; envelope-from=libc-alpha-bounces+incoming=patchwork.ozlabs.org@sourceware.org; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; secure) header.d=sourceware.org header.i=@sourceware.org header.a=rsa-sha256 header.s=default header.b=SePWS09x; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4QhfD75rl7z20QH for ; Thu, 15 Jun 2023 20:48:55 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id CCD3D3857704 for ; Thu, 15 Jun 2023 10:48:53 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org CCD3D3857704 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1686826133; bh=41wY3qjNEn1GR7gtbVDIsTMG6kNZ2vXAoC/mxinsnH0=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=SePWS09x3wTat56w6t3Ower7UWh472rXjcIxCjBsDcHYNxIHu0ExkUw28EFlpUEB2 +43PmZfeRqU5pSFumh437T+3km1D/wC3xJB/z+SahovETGOlnmqnODjkCTGDndFUY6 FXyfOmph0xiKegR1IDb+HGDyMvtBwHDt9mNL3fas= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id C21AA3858020 for ; Thu, 15 Jun 2023 10:48:38 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org C21AA3858020 Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-607-fdT86qXjP1S9Jj6odff-mQ-1; Thu, 15 Jun 2023 06:48:37 -0400 X-MC-Unique: fdT86qXjP1S9Jj6odff-mQ-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 1633C3849539 for ; Thu, 15 Jun 2023 10:48:37 +0000 (UTC) Received: from oldenburg.str.redhat.com (unknown [10.2.16.15]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 3D49A40CF8EF for ; Thu, 15 Jun 2023 10:48:36 +0000 (UTC) To: libc-alpha@sourceware.org Subject: [PATCH] string: strerror must not return NULL (bug 30555) Date: Thu, 15 Jun 2023 12:48:34 +0200 Message-ID: <87r0qd6lx9.fsf@oldenburg.str.redhat.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.2 (gnu/linux) MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-10.8 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) 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: Florian Weimer via Libc-alpha From: Florian Weimer Reply-To: Florian Weimer Errors-To: libc-alpha-bounces+incoming=patchwork.ozlabs.org@sourceware.org Sender: "Libc-alpha" For strerror, this fixes commit 28aff047818eb1726394296d27b ("string: Implement strerror in terms of strerror_l"). This commit avoids returning NULL for strerror_l as well, although POSIX allows this behavior for strerror_l. Tested on x86_64-linux-gnu. The test reproduces the bug before the fix. --- string/Makefile | 1 + string/strerror_l.c | 13 +++++--- string/tst-strerror-fail.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 4 deletions(-) base-commit: 388ae538ddcb05c7d8966147b488a5f6e481656e diff --git a/string/Makefile b/string/Makefile index 0ad276cc6a..d3106d10a9 100644 --- a/string/Makefile +++ b/string/Makefile @@ -178,6 +178,7 @@ tests := \ tst-endian \ tst-inlcall \ tst-memmove-overflow \ + tst-strerror-fail \ tst-strfry \ tst-strlcat \ tst-strlcpy \ diff --git a/string/strerror_l.c b/string/strerror_l.c index 7fe9b1d903..5d370c9cf1 100644 --- a/string/strerror_l.c +++ b/string/strerror_l.c @@ -43,10 +43,15 @@ __strerror_l (int errnum, locale_t loc) struct tls_internal_t *tls_internal = __glibc_tls_internal (); free (tls_internal->strerror_l_buf); if (__asprintf (&tls_internal->strerror_l_buf, "%s%d", - translate ("Unknown error ", loc), errnum) == -1) - tls_internal->strerror_l_buf = NULL; - - err = tls_internal->strerror_l_buf; + translate ("Unknown error ", loc), errnum) > 0) + err = tls_internal->strerror_l_buf; + else + { + /* The pointer was freed above. */ + tls_internal->strerror_l_buf = NULL; + /* Provide a fallback translation. */ + err = (char *) translate ("Unknown error", loc); + } } else err = (char *) translate (err, loc); diff --git a/string/tst-strerror-fail.c b/string/tst-strerror-fail.c new file mode 100644 index 0000000000..e0fa45ab2b --- /dev/null +++ b/string/tst-strerror-fail.c @@ -0,0 +1,77 @@ +/* Check that strerror, strerror_l do not return NULL on failure (bug 30555). + Copyright (C) 2023 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 + +/* Interposed malloc that can be used to inject allocation failures. */ + +static volatile bool fail_malloc; + +void * +malloc (size_t size) +{ + if (fail_malloc) + return NULL; + + static void *(*original_malloc) (size_t); + if (original_malloc == NULL) + original_malloc = xdlsym (RTLD_NEXT, "malloc"); + return original_malloc (size); +} + +/* Callbacks for the actual tests. Use fork to run both tests with a + clean state. */ + +static void +test_strerror (void *closure) +{ + fail_malloc = true; + const char *s = strerror (999); + fail_malloc = false; + TEST_COMPARE_STRING (s, "Unknown error"); +} + +static void +test_strerror_l (void *closure) +{ + locale_t loc = newlocale (LC_ALL, "C", (locale_t) 0); + TEST_VERIFY (loc != (locale_t) 0); + fail_malloc = true; + const char *s = strerror_l (999, loc); + fail_malloc = false; + TEST_COMPARE_STRING (s, "Unknown error"); + freelocale (loc); +} + +static int +do_test (void) +{ + support_isolate_in_subprocess (test_strerror, NULL); + support_isolate_in_subprocess (test_strerror_l, NULL); + + return 0; +} + +#include