From patchwork Thu Apr 30 22:12:32 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martin Sebor X-Patchwork-Id: 38894 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 569883991C3C; Thu, 30 Apr 2020 22:12:40 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 569883991C3C DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1588284760; bh=cxvNB+L5kMzwVPgDAZNrrWZv7LSqhulRqVOBf7A6LQY=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=e/2cR8hcKcNRhxrQS/s/jCGzucquaoVR56fsgJoTzu2IYiFeGmA/+xMrnc3/WqU/2 9954DzITUfKR8HVOUDSUNpPQcVfTPErJ1dA1ku2xeMLUCOYJuzxbvt4HBErIOSjCl9 NVO0XeMl3MGap/NYrWWUwkPMCHCt9f51LtmVKtH0= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-qv1-xf2e.google.com (mail-qv1-xf2e.google.com [IPv6:2607:f8b0:4864:20::f2e]) by sourceware.org (Postfix) with ESMTPS id D790E3972421 for ; Thu, 30 Apr 2020 22:12:35 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org D790E3972421 Received: by mail-qv1-xf2e.google.com with SMTP id v10so3913204qvr.2 for ; Thu, 30 Apr 2020 15:12:35 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:to:from:subject:message-id:date:user-agent :mime-version:content-language; bh=cxvNB+L5kMzwVPgDAZNrrWZv7LSqhulRqVOBf7A6LQY=; b=oNsjzhcvIIbpJbTkd9V0Hq6IS3bU7DxOSU+emo7PiGCkaz9rh1kPbwQAkj0ydTO+eW xuVcX4cddhnWscp1w/WUTwBeYiWu45Rdaoms95+DHMcJq1WBrSOdXPCrMeM0AsQxYPdo xacF1wKCxEp7HqMJqVmsPP9ZZ4+Nb3U0g1OPHyvkE2FV4ukeVK5TsiwlY3muIwyB8TSk 1GHDw8FMcRGkOrrpSmkI3UKbMhE+wbZRmbm93zXYz7OJtnGQJBjrYFna74i/MkztkA7Q 8jZUIABetmp9Mfqd3FK8lJPtcpCz8ZYQApC3uIEMWM0W8W/A9PldT6wQo4kHQHSvcfyW sp5w== X-Gm-Message-State: AGi0PuaLwNtA1cfie+kgT5xeSiU2SaZevOX8nu1Qbt/lxXD5SpS5n4w0 uhPXc9w7DzyHMTljh95ce/OS7Jcu X-Google-Smtp-Source: APiQypIG6jpig1Rc+7TsTt/5lYzJ5vqxhrZfUYzkVXsm4k+qZKsIzAiCsAjs0dAVwqRXTm4Ll3u3BA== X-Received: by 2002:a0c:b5dd:: with SMTP id o29mr1184207qvf.87.1588284755110; Thu, 30 Apr 2020 15:12:35 -0700 (PDT) Received: from [192.168.0.41] (71-218-0-44.hlrn.qwest.net. [71.218.0.44]) by smtp.gmail.com with ESMTPSA id t75sm1207705qke.127.2020.04.30.15.12.33 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Thu, 30 Apr 2020 15:12:33 -0700 (PDT) To: GNU C Library Subject: [PATCH] improve out-of-bounds checking with GCC 10 attribute access [BZ #25219] Message-ID: <1b67cd2a-3254-fbd4-4345-7bc282f7cdd0@gmail.com> Date: Thu, 30 Apr 2020 16:12:32 -0600 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.6.1 MIME-Version: 1.0 Content-Language: en-US X-Spam-Status: No, score=-21.1 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, 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: Martin Sebor via Libc-alpha From: Martin Sebor Reply-To: Martin Sebor Errors-To: libc-alpha-bounces@sourceware.org Sender: "Libc-alpha" To extend the detection of out-of-bounds accesses by GCC built-in functions like memcpy and strcpy to user-defined functions, GCC 10 introduces a new function attribute named access with this syntax: access (access-mode, ref-index [, size-index]) Besides specifying the form of the access (read-only, read-write, and write-only), it associates the pointer parameter with a parameter that indicates the size (in elements) of the array the pointer points to. The attribute lets GCC diagnose not just the subset of out-of-bounds accesses involving constant offsets and sizes but also those where the offsets into the buffers or their sizes aren't constant (they may be in some range whose lower or upper bound makes the access decidedly invalid). The constant offset/size limitation affects _FORTIFY_SOURCE but not GCC warnings. The attached patch adds the new access attribute to the subset of Glibc declarations that are already covered by _FORTIFY_SOURCE and that don't have corresponding GCC built-in equivalents. Besides building Glibc and running the tests I've tested the patch by creating calls to the modified functions, one valid and one with an out-of-bounds access, and checking for the expected warnings. The test is attached for reference (I don't know of an easy way to add it to the Glibc test suite). Martin PS A further extension (not in this patch) is also associating const pointer parameters with attribute access. This lets GCC diagnose out-of-bounds reads and in the future may also let it diagnose uninitialized reads through such pointers. BZ #25219 - improve out-of-bounds checking with GCC 10 attribute access ChangeLog: * misc/sys/cdefs.h (__attr_access): New macro. * libio/bits/stdio2.h (__fgets_chk): Add attribute access. (__fgets_unlocked_chk): Same. * posix/bits/unistd.h (__read_chk, __read_alias): Same. (__pread_chk, __pread64_chk, __pread_alias, __pread64_alias): Same. (__readlink_chk, __readlink_alias): Same. (__readlinkat_chk, __readlinkat_alias): Same. (__getcwd_chk, __getcwd_alias): Same. (__confstr_chk, __confstr_alias): Same. (__getgroups_chk, __getgroups_alias): Same. (__ttyname_r_chk, __ttyname_r_alias): Same. (__getlogin_r_chk, __getlogin_r_alias): Same. (__gethostname_chk, __gethostname_alias): Same. (__getdomainname_chk, __getdomainname_alias): Same. * posix/unistd.h (read, write, pread, pwrite): Same. (pread64, pwrite64): Same. (getcwd, confstr, getgrtoups, ttyname_r): Same. (readlinkat, getlogin_r, gethostname, sethostname): Same. (getdomainname, setdomainname, swab, genentropy): Same. * stdlib/bits/stdlib.h (__ptsname_r_chk): Same (__mbstowcs_chk, __mbstowcs_alias): Same (__wcstombs_chk, __wcstombs_alias): Same * stdlib/stdlib.h (mbstowcs, wcstombs): Same * string/bits/string_fortified.h (explicit_bzero_chk): Same * string/string.h (meccmpy, memrrchr, strxfrm, strcoll_l): Same. (memmem, __xpg_strerror_r, strerror_r): Same. (explicit_bzero, memfrob): Same. diff --git a/libio/bits/stdio2.h b/libio/bits/stdio2.h index 60bc81735e..eff1c1fc09 100644 --- a/libio/bits/stdio2.h +++ b/libio/bits/stdio2.h @@ -241,7 +241,8 @@ gets (char *__str) #endif extern char *__fgets_chk (char *__restrict __s, size_t __size, int __n, - FILE *__restrict __stream) __wur; + FILE *__restrict __stream) + __wur __attr_access ((__read_only__, 1, 2)); extern char *__REDIRECT (__fgets_alias, (char *__restrict __s, int __n, FILE *__restrict __stream), fgets) __wur; @@ -299,7 +300,8 @@ fread (void *__restrict __ptr, size_t __size, size_t __n, #ifdef __USE_GNU extern char *__fgets_unlocked_chk (char *__restrict __s, size_t __size, - int __n, FILE *__restrict __stream) __wur; + int __n, FILE *__restrict __stream) + __wur __attr_access ((__write_only__, 1, 2)); extern char *__REDIRECT (__fgets_unlocked_alias, (char *__restrict __s, int __n, FILE *__restrict __stream), fgets_unlocked) __wur; diff --git a/misc/sys/cdefs.h b/misc/sys/cdefs.h index 9fa371ab86..4365a39caf 100644 --- a/misc/sys/cdefs.h +++ b/misc/sys/cdefs.h @@ -548,4 +548,14 @@ _Static_assert (0, "IEEE 128-bits long double requires redirection on this platf # define __HAVE_GENERIC_SELECTION 0 #endif +#if __GNUC_PREREQ (10, 0) +/* Denotes a function pointer argument ref-index that can be used + to access size-index elements of the pointed-to array according + to access mode: + access (access-mode, [, ]) */ +#define __attr_access(x) __attribute__ ((__access__ x)) +#else +# define __attr_access(x) +#endif + #endif /* sys/cdefs.h */ diff --git a/posix/bits/unistd.h b/posix/bits/unistd.h index b8a8211d83..725a83eb0d 100644 --- a/posix/bits/unistd.h +++ b/posix/bits/unistd.h @@ -21,9 +21,11 @@ #endif extern ssize_t __read_chk (int __fd, void *__buf, size_t __nbytes, - size_t __buflen) __wur; + size_t __buflen) + __wur __attr_access ((__write_only__, 2, 3)); extern ssize_t __REDIRECT (__read_alias, (int __fd, void *__buf, - size_t __nbytes), read) __wur; + size_t __nbytes), read) + __wur __attr_access ((__write_only__, 2, 3)); extern ssize_t __REDIRECT (__read_chk_warn, (int __fd, void *__buf, size_t __nbytes, size_t __buflen), __read_chk) @@ -46,15 +48,19 @@ read (int __fd, void *__buf, size_t __nbytes) #ifdef __USE_UNIX98 extern ssize_t __pread_chk (int __fd, void *__buf, size_t __nbytes, - __off_t __offset, size_t __bufsize) __wur; + __off_t __offset, size_t __bufsize) + __wur __attr_access ((__write_only__, 2, 3)); extern ssize_t __pread64_chk (int __fd, void *__buf, size_t __nbytes, - __off64_t __offset, size_t __bufsize) __wur; + __off64_t __offset, size_t __bufsize) + __wur __attr_access ((__write_only__, 2, 3)); extern ssize_t __REDIRECT (__pread_alias, (int __fd, void *__buf, size_t __nbytes, - __off_t __offset), pread) __wur; + __off_t __offset), pread) + __wur __attr_access ((__write_only__, 2, 3)); extern ssize_t __REDIRECT (__pread64_alias, (int __fd, void *__buf, size_t __nbytes, - __off64_t __offset), pread64) __wur; + __off64_t __offset), pread64) + __wur __attr_access ((__write_only__, 2, 3)); extern ssize_t __REDIRECT (__pread_chk_warn, (int __fd, void *__buf, size_t __nbytes, __off_t __offset, size_t __bufsize), __pread_chk) @@ -123,11 +129,11 @@ pread64 (int __fd, void *__buf, size_t __nbytes, __off64_t __offset) extern ssize_t __readlink_chk (const char *__restrict __path, char *__restrict __buf, size_t __len, size_t __buflen) - __THROW __nonnull ((1, 2)) __wur; + __THROW __nonnull ((1, 2)) __wur __attr_access ((__write_only__, 2, 3)); extern ssize_t __REDIRECT_NTH (__readlink_alias, (const char *__restrict __path, char *__restrict __buf, size_t __len), readlink) - __nonnull ((1, 2)) __wur; + __nonnull ((1, 2)) __wur __attr_access ((__write_only__, 2, 3)); extern ssize_t __REDIRECT_NTH (__readlink_chk_warn, (const char *__restrict __path, char *__restrict __buf, size_t __len, @@ -155,12 +161,12 @@ __NTH (readlink (const char *__restrict __path, char *__restrict __buf, extern ssize_t __readlinkat_chk (int __fd, const char *__restrict __path, char *__restrict __buf, size_t __len, size_t __buflen) - __THROW __nonnull ((2, 3)) __wur; + __THROW __nonnull ((2, 3)) __wur __attr_access ((__write_only__, 3, 4)); extern ssize_t __REDIRECT_NTH (__readlinkat_alias, (int __fd, const char *__restrict __path, char *__restrict __buf, size_t __len), readlinkat) - __nonnull ((2, 3)) __wur; + __nonnull ((2, 3)) __wur __attr_access ((__write_only__, 3, 4)); extern ssize_t __REDIRECT_NTH (__readlinkat_chk_warn, (int __fd, const char *__restrict __path, char *__restrict __buf, size_t __len, @@ -187,9 +193,10 @@ __NTH (readlinkat (int __fd, const char *__restrict __path, #endif extern char *__getcwd_chk (char *__buf, size_t __size, size_t __buflen) - __THROW __wur; + __THROW __wur __attr_access ((__write_only__, 1, 2)); extern char *__REDIRECT_NTH (__getcwd_alias, - (char *__buf, size_t __size), getcwd) __wur; + (char *__buf, size_t __size), getcwd) + __wur __attr_access ((__write_only__, 1, 2)); extern char *__REDIRECT_NTH (__getcwd_chk_warn, (char *__buf, size_t __size, size_t __buflen), __getcwd_chk) @@ -212,7 +219,7 @@ __NTH (getcwd (char *__buf, size_t __size)) #if defined __USE_MISC || defined __USE_XOPEN_EXTENDED extern char *__getwd_chk (char *__buf, size_t buflen) - __THROW __nonnull ((1)) __wur; + __THROW __nonnull ((1)) __wur __attr_access ((__write_only__, 1, 2)); extern char *__REDIRECT_NTH (__getwd_warn, (char *__buf), getwd) __nonnull ((1)) __wur __warnattr ("please use getcwd instead, as getwd " "doesn't specify buffer size"); @@ -227,9 +234,11 @@ __NTH (getwd (char *__buf)) #endif extern size_t __confstr_chk (int __name, char *__buf, size_t __len, - size_t __buflen) __THROW; + size_t __buflen) __THROW + __attr_access ((__write_only__, 2, 3)); extern size_t __REDIRECT_NTH (__confstr_alias, (int __name, char *__buf, - size_t __len), confstr); + size_t __len), confstr) + __attr_access ((__write_only__, 2, 3)); extern size_t __REDIRECT_NTH (__confstr_chk_warn, (int __name, char *__buf, size_t __len, size_t __buflen), __confstr_chk) @@ -252,9 +261,9 @@ __NTH (confstr (int __name, char *__buf, size_t __len)) extern int __getgroups_chk (int __size, __gid_t __list[], size_t __listlen) - __THROW __wur; + __THROW __wur __attr_access ((__write_only__, 2, 1)); extern int __REDIRECT_NTH (__getgroups_alias, (int __size, __gid_t __list[]), - getgroups) __wur; + getgroups) __wur __attr_access ((__write_only__, 2, 1)); extern int __REDIRECT_NTH (__getgroups_chk_warn, (int __size, __gid_t __list[], size_t __listlen), __getgroups_chk) @@ -277,7 +286,8 @@ __NTH (getgroups (int __size, __gid_t __list[])) extern int __ttyname_r_chk (int __fd, char *__buf, size_t __buflen, - size_t __nreal) __THROW __nonnull ((2)); + size_t __nreal) __THROW __nonnull ((2)) + __attr_access ((__write_only__, 2, 3)); extern int __REDIRECT_NTH (__ttyname_r_alias, (int __fd, char *__buf, size_t __buflen), ttyname_r) __nonnull ((2)); @@ -304,7 +314,7 @@ __NTH (ttyname_r (int __fd, char *__buf, size_t __buflen)) #ifdef __USE_POSIX199506 extern int __getlogin_r_chk (char *__buf, size_t __buflen, size_t __nreal) - __nonnull ((1)); + __nonnull ((1)) __attr_access ((__write_only__, 1, 2)); extern int __REDIRECT (__getlogin_r_alias, (char *__buf, size_t __buflen), getlogin_r) __nonnull ((1)); extern int __REDIRECT (__getlogin_r_chk_warn, @@ -331,9 +341,10 @@ getlogin_r (char *__buf, size_t __buflen) #if defined __USE_MISC || defined __USE_UNIX98 extern int __gethostname_chk (char *__buf, size_t __buflen, size_t __nreal) - __THROW __nonnull ((1)); + __THROW __nonnull ((1)) __attr_access ((__write_only__, 1, 2)); extern int __REDIRECT_NTH (__gethostname_alias, (char *__buf, size_t __buflen), - gethostname) __nonnull ((1)); + gethostname) + __nonnull ((1)) __attr_access ((__write_only__, 1, 2)); extern int __REDIRECT_NTH (__gethostname_chk_warn, (char *__buf, size_t __buflen, size_t __nreal), __gethostname_chk) @@ -358,10 +369,11 @@ __NTH (gethostname (char *__buf, size_t __buflen)) #if defined __USE_MISC || (defined __USE_XOPEN && !defined __USE_UNIX98) extern int __getdomainname_chk (char *__buf, size_t __buflen, size_t __nreal) - __THROW __nonnull ((1)) __wur; + __THROW __nonnull ((1)) __wur __attr_access ((__write_only__, 1, 2)); extern int __REDIRECT_NTH (__getdomainname_alias, (char *__buf, size_t __buflen), - getdomainname) __nonnull ((1)) __wur; + getdomainname) __nonnull ((1)) + __wur __attr_access ((__write_only__, 1, 2)); extern int __REDIRECT_NTH (__getdomainname_chk_warn, (char *__buf, size_t __buflen, size_t __nreal), __getdomainname_chk) diff --git a/posix/unistd.h b/posix/unistd.h index 0dd4200ad6..a4c831ae90 100644 --- a/posix/unistd.h +++ b/posix/unistd.h @@ -357,13 +357,15 @@ extern int close (int __fd); This function is a cancellation point and therefore not marked with __THROW. */ -extern ssize_t read (int __fd, void *__buf, size_t __nbytes) __wur; +extern ssize_t read (int __fd, void *__buf, size_t __nbytes) __wur + __attr_access ((__write_only__, 2, 3)); /* Write N bytes of BUF to FD. Return the number written, or -1. This function is a cancellation point and therefore not marked with __THROW. */ -extern ssize_t write (int __fd, const void *__buf, size_t __n) __wur; +extern ssize_t write (int __fd, const void *__buf, size_t __n) __wur + __attr_access ((__read_only__, 2, 3)); #if defined __USE_UNIX98 || defined __USE_XOPEN2K8 # ifndef __USE_FILE_OFFSET64 @@ -374,7 +376,8 @@ extern ssize_t write (int __fd, const void *__buf, size_t __n) __wur; This function is a cancellation point and therefore not marked with __THROW. */ extern ssize_t pread (int __fd, void *__buf, size_t __nbytes, - __off_t __offset) __wur; + __off_t __offset) __wur + __attr_access ((__write_only__, 2, 3)); /* Write N bytes of BUF to FD at the given position OFFSET without changing the file pointer. Return the number written, or -1. @@ -382,15 +385,19 @@ extern ssize_t pread (int __fd, void *__buf, size_t __nbytes, This function is a cancellation point and therefore not marked with __THROW. */ extern ssize_t pwrite (int __fd, const void *__buf, size_t __n, - __off_t __offset) __wur; + __off_t __offset) __wur + __attr_access ((__read_only__, 2, 3)); + # else # ifdef __REDIRECT extern ssize_t __REDIRECT (pread, (int __fd, void *__buf, size_t __nbytes, __off64_t __offset), - pread64) __wur; + pread64) __wur + __attr_access ((__write_only__, 2, 3)); extern ssize_t __REDIRECT (pwrite, (int __fd, const void *__buf, size_t __nbytes, __off64_t __offset), - pwrite64) __wur; + pwrite64) __wur + __attr_access ((__read_only__, 2, 3)); # else # define pread pread64 # define pwrite pwrite64 @@ -402,11 +409,13 @@ extern ssize_t __REDIRECT (pwrite, (int __fd, const void *__buf, changing the file pointer. Return the number read, -1 for errors or 0 for EOF. */ extern ssize_t pread64 (int __fd, void *__buf, size_t __nbytes, - __off64_t __offset) __wur; + __off64_t __offset) __wur + __attr_access ((__write_only__, 2, 3)); /* Write N bytes of BUF to FD at the given position OFFSET without changing the file pointer. Return the number written, or -1. */ extern ssize_t pwrite64 (int __fd, const void *__buf, size_t __n, - __off64_t __offset) __wur; + __off64_t __offset) __wur + __attr_access ((__read_only__, 2, 3)); # endif #endif @@ -523,7 +532,8 @@ extern char *get_current_dir_name (void) __THROW; If successful, return BUF. If not, put an error message in BUF and return NULL. BUF should be at least PATH_MAX bytes long. */ extern char *getwd (char *__buf) - __THROW __nonnull ((1)) __attribute_deprecated__ __wur; + __THROW __nonnull ((1)) __attribute_deprecated__ __wur + __attr_access ((__write_only__, 1)); #endif @@ -620,7 +630,8 @@ extern long int sysconf (int __name) __THROW; #ifdef __USE_POSIX2 /* Get the value of the string-valued system variable NAME. */ -extern size_t confstr (int __name, char *__buf, size_t __len) __THROW; +extern size_t confstr (int __name, char *__buf, size_t __len) __THROW + __attribute__ ((access (__write_only__, 2, 3))); #endif @@ -686,8 +697,8 @@ extern __gid_t getegid (void) __THROW; /* If SIZE is zero, return the number of supplementary groups the calling process is in. Otherwise, fill in the group IDs of its supplementary groups in LIST and return the number written. */ -extern int getgroups (int __size, __gid_t __list[]) __THROW __wur; - +extern int getgroups (int __size, __gid_t __list[]) __THROW __wur + __attr_access ((__write_only__, 2, 1)); #ifdef __USE_GNU /* Return nonzero iff the calling process is in group GID. */ extern int group_member (__gid_t __gid) __THROW; @@ -772,7 +783,7 @@ extern char *ttyname (int __fd) __THROW; /* Store at most BUFLEN characters of the pathname of the terminal FD is open on in BUF. Return 0 on success, otherwise an error number. */ extern int ttyname_r (int __fd, char *__buf, size_t __buflen) - __THROW __nonnull ((2)) __wur; + __THROW __nonnull ((2)) __wur __attr_access ((__write_only__, 2, 3)); /* Return 1 if FD is a valid descriptor associated with a terminal, zero if not. */ @@ -807,7 +818,8 @@ extern int symlink (const char *__from, const char *__to) Returns the number of characters read, or -1 for errors. */ extern ssize_t readlink (const char *__restrict __path, char *__restrict __buf, size_t __len) - __THROW __nonnull ((1, 2)) __wur; + __THROW __nonnull ((1, 2)) __wur __attr_access ((__write_only__, 2, 3)); + #endif /* Use POSIX.1-2001. */ #ifdef __USE_ATFILE @@ -818,7 +830,7 @@ extern int symlinkat (const char *__from, int __tofd, /* Like readlink but a relative PATH is interpreted relative to FD. */ extern ssize_t readlinkat (int __fd, const char *__restrict __path, char *__restrict __buf, size_t __len) - __THROW __nonnull ((2, 3)) __wur; + __THROW __nonnull ((2, 3)) __wur __attr_access ((__read_only__, 3, 4)); #endif /* Remove the link NAME. */ @@ -853,7 +865,8 @@ extern char *getlogin (void); This function is a possible cancellation point and therefore not marked with __THROW. */ -extern int getlogin_r (char *__name, size_t __name_len) __nonnull ((1)); +extern int getlogin_r (char *__name, size_t __name_len) __nonnull ((1)) + __attr_access ((__write_only__, 1, 2)); #endif #ifdef __USE_MISC @@ -874,7 +887,8 @@ extern int setlogin (const char *__name) __THROW __nonnull ((1)); /* Put the name of the current host in no more than LEN bytes of NAME. The result is null-terminated if LEN is large enough for the full name and the terminator. */ -extern int gethostname (char *__name, size_t __len) __THROW __nonnull ((1)); +extern int gethostname (char *__name, size_t __len) __THROW __nonnull ((1)) + __attr_access ((__write_only__, 1, 2)); #endif @@ -882,7 +896,7 @@ extern int gethostname (char *__name, size_t __len) __THROW __nonnull ((1)); /* Set the name of the current host to NAME, which is LEN bytes long. This call is restricted to the super-user. */ extern int sethostname (const char *__name, size_t __len) - __THROW __nonnull ((1)) __wur; + __THROW __nonnull ((1)) __wur __attr_access ((__read_only__, 1, 2)); /* Set the current machine's Internet number to ID. This call is restricted to the super-user. */ @@ -893,10 +907,9 @@ extern int sethostid (long int __id) __THROW __wur; Called just like `gethostname' and `sethostname'. The NIS domain name is usually the empty string when not using NIS. */ extern int getdomainname (char *__name, size_t __len) - __THROW __nonnull ((1)) __wur; + __THROW __nonnull ((1)) __wur __attr_access ((__write_only__, 1, 2)); extern int setdomainname (const char *__name, size_t __len) - __THROW __nonnull ((1)) __wur; - + __THROW __nonnull ((1)) __wur __attr_access ((__read_only__, 1, 2)); /* Revoke access permissions to all processes currently communicating with the control terminal, and then send a SIGHUP signal to the process @@ -1131,7 +1144,9 @@ extern char *crypt (const char *__key, const char *__salt) range [FROM - N + 1, FROM - 1]. If N is odd the first byte in FROM is without partner. */ extern void swab (const void *__restrict __from, void *__restrict __to, - ssize_t __n) __THROW __nonnull ((1, 2)); + ssize_t __n) __THROW __nonnull ((1, 2)) + __attr_access ((__read_only__, 1, 3)) + __attr_access ((__write_only__, 2, 3)); #endif @@ -1158,7 +1173,8 @@ extern int pthread_atfork (void (*__prepare) (void), #ifdef __USE_MISC /* Write LENGTH bytes of randomness starting at BUFFER. Return 0 on success or -1 on error. */ -int getentropy (void *__buffer, size_t __length) __wur; +int getentropy (void *__buffer, size_t __length) __wur + __attr_access ((__write_only__, 1, 2)); #endif /* Define some macros helping to catch buffer overflows. */ diff --git a/stdlib/bits/stdlib.h b/stdlib/bits/stdlib.h index bfdee75073..9134d3f36b 100644 --- a/stdlib/bits/stdlib.h +++ b/stdlib/bits/stdlib.h @@ -50,10 +50,11 @@ __NTH (realpath (const char *__restrict __name, char *__restrict __resolved)) extern int __ptsname_r_chk (int __fd, char *__buf, size_t __buflen, - size_t __nreal) __THROW __nonnull ((2)); + size_t __nreal) __THROW __nonnull ((2)) + __attr_access ((__write_only__, 2, 3)); extern int __REDIRECT_NTH (__ptsname_r_alias, (int __fd, char *__buf, size_t __buflen), ptsname_r) - __nonnull ((2)); + __nonnull ((2)) __attr_access ((__write_only__, 2, 3)); extern int __REDIRECT_NTH (__ptsname_r_chk_warn, (int __fd, char *__buf, size_t __buflen, size_t __nreal), __ptsname_r_chk) @@ -97,11 +98,13 @@ __NTH (wctomb (char *__s, wchar_t __wchar)) extern size_t __mbstowcs_chk (wchar_t *__restrict __dst, const char *__restrict __src, - size_t __len, size_t __dstlen) __THROW; + size_t __len, size_t __dstlen) __THROW + __attr_access ((__write_only__, 1, 3)) __attr_access ((__read_only__, 2)); extern size_t __REDIRECT_NTH (__mbstowcs_alias, (wchar_t *__restrict __dst, const char *__restrict __src, - size_t __len), mbstowcs); + size_t __len), mbstowcs) + __attr_access ((__write_only__, 1, 3)) __attr_access ((__read_only__, 2)); extern size_t __REDIRECT_NTH (__mbstowcs_chk_warn, (wchar_t *__restrict __dst, const char *__restrict __src, @@ -129,11 +132,13 @@ __NTH (mbstowcs (wchar_t *__restrict __dst, const char *__restrict __src, extern size_t __wcstombs_chk (char *__restrict __dst, const wchar_t *__restrict __src, - size_t __len, size_t __dstlen) __THROW; + size_t __len, size_t __dstlen) __THROW + __attr_access ((__write_only__, 1, 3)) __attr_access ((__read_only__, 2)); extern size_t __REDIRECT_NTH (__wcstombs_alias, (char *__restrict __dst, const wchar_t *__restrict __src, - size_t __len), wcstombs); + size_t __len), wcstombs) + __attr_access ((__write_only__, 1, 3)) __attr_access ((__read_only__, 2)); extern size_t __REDIRECT_NTH (__wcstombs_chk_warn, (char *__restrict __dst, const wchar_t *__restrict __src, diff --git a/stdlib/stdlib.h b/stdlib/stdlib.h index 9b7537c545..dd779bd740 100644 --- a/stdlib/stdlib.h +++ b/stdlib/stdlib.h @@ -931,12 +931,13 @@ extern int wctomb (char *__s, wchar_t __wchar) __THROW; /* Convert a multibyte string to a wide char string. */ extern size_t mbstowcs (wchar_t *__restrict __pwcs, - const char *__restrict __s, size_t __n) __THROW; + const char *__restrict __s, size_t __n) __THROW + __attr_access ((__write_only__, 1, 3)) __attr_access ((__read_only__, 2)); /* Convert a wide char string to multibyte string. */ extern size_t wcstombs (char *__restrict __s, const wchar_t *__restrict __pwcs, size_t __n) - __THROW; - + __THROW + __attr_access ((__write_only__, 1, 3)) __attr_access ((__read_only__, 2)); #ifdef __USE_MISC /* Determine whether the string value of RESPONSE matches the affirmation @@ -990,7 +991,7 @@ extern char *ptsname (int __fd) __THROW __wur; terminal associated with the master FD is open on in BUF. Return 0 on success, otherwise an error number. */ extern int ptsname_r (int __fd, char *__buf, size_t __buflen) - __THROW __nonnull ((2)); + __THROW __nonnull ((2)) __attr_access ((__write_only__, 2, 3)); /* Open a master pseudo terminal and return its file descriptor. */ extern int getpt (void); diff --git a/string/bits/string_fortified.h b/string/bits/string_fortified.h index e4d07cb50c..309d0f39b2 100644 --- a/string/bits/string_fortified.h +++ b/string/bits/string_fortified.h @@ -75,7 +75,7 @@ __NTH (memset (void *__dest, int __ch, size_t __len)) # include void __explicit_bzero_chk (void *__dest, size_t __len, size_t __destlen) - __THROW __nonnull ((1)); + __THROW __nonnull ((1)) __attr_access ((__write_only__, 1, 2)); __fortify_function void __NTH (explicit_bzero (void *__dest, size_t __len)) @@ -108,7 +108,8 @@ __NTH (strncpy (char *__restrict __dest, const char *__restrict __src, /* XXX We have no corresponding builtin yet. */ extern char *__stpncpy_chk (char *__dest, const char *__src, size_t __n, - size_t __destlen) __THROW; + size_t __destlen) __THROW + __attr_access ((__write_only__, 1, 3)) __attr_access ((__read_only__, 2)); extern char *__REDIRECT_NTH (__stpncpy_alias, (char *__dest, const char *__src, size_t __n), stpncpy); diff --git a/string/string.h b/string/string.h index a0f2860cc2..e85e06ddc4 100644 --- a/string/string.h +++ b/string/string.h @@ -53,7 +53,7 @@ extern void *memmove (void *__dest, const void *__src, size_t __n) #if defined __USE_MISC || defined __USE_XOPEN || __GLIBC_USE (ISOC2X) extern void *memccpy (void *__restrict __dest, const void *__restrict __src, int __c, size_t __n) - __THROW __nonnull ((1, 2)); + __THROW __nonnull ((1, 2)) __attr_access ((__write_only__, 1, 4)); #endif /* Misc || X/Open. */ @@ -108,9 +108,11 @@ extern void *rawmemchr (const void *__s, int __c) /* Search N bytes of S for the final occurrence of C. */ # ifdef __CORRECT_ISO_CPP_STRING_H_PROTO extern "C++" void *memrchr (void *__s, int __c, size_t __n) - __THROW __asm ("memrchr") __attribute_pure__ __nonnull ((1)); + __THROW __asm ("memrchr") __attribute_pure__ __nonnull ((1)) + __attr_access ((__read_only__, 1, 3)); extern "C++" const void *memrchr (const void *__s, int __c, size_t __n) - __THROW __asm ("memrchr") __attribute_pure__ __nonnull ((1)); + __THROW __asm ("memrchr") __attribute_pure__ __nonnull ((1)) + __attr_access ((__read_only__, 1, 3)); # else extern void *memrchr (const void *__s, int __c, size_t __n) __THROW __attribute_pure__ __nonnull ((1)); @@ -146,7 +148,7 @@ extern int strcoll (const char *__s1, const char *__s2) /* Put a transformation of SRC into no more than N bytes of DEST. */ extern size_t strxfrm (char *__restrict __dest, const char *__restrict __src, size_t __n) - __THROW __nonnull ((2)); + __THROW __nonnull ((2)) __attr_access ((__write_only__, 1, 3)); #ifdef __USE_XOPEN2K8 /* POSIX.1-2008 extended locale interface (see locale.h). */ @@ -158,7 +160,8 @@ extern int strcoll_l (const char *__s1, const char *__s2, locale_t __l) /* Put a transformation of SRC into no more than N bytes of DEST, using sorting rules from L. */ extern size_t strxfrm_l (char *__dest, const char *__src, size_t __n, - locale_t __l) __THROW __nonnull ((2, 4)); + locale_t __l) __THROW __nonnull ((2, 4)) + __attr_access ((__write_only__, 1, 3)); #endif #if (defined __USE_XOPEN_EXTENDED || defined __USE_XOPEN2K8 \ @@ -368,7 +371,9 @@ extern char *strcasestr (const char *__haystack, const char *__needle) HAYSTACK is HAYSTACKLEN bytes long. */ extern void *memmem (const void *__haystack, size_t __haystacklen, const void *__needle, size_t __needlelen) - __THROW __attribute_pure__ __nonnull ((1, 3)); + __THROW __attribute_pure__ __nonnull ((1, 3)) + __attr_access ((__read_only__, 1, 2)) + __attr_access ((__read_only__, 3, 4)); /* Copy N bytes of SRC to DEST, return pointer to bytes after the last written byte. */ @@ -409,17 +414,18 @@ extern char *strerror (int __errnum) __THROW; # ifdef __REDIRECT_NTH extern int __REDIRECT_NTH (strerror_r, (int __errnum, char *__buf, size_t __buflen), - __xpg_strerror_r) __nonnull ((2)); + __xpg_strerror_r) __nonnull ((2)) + __attr_access ((__write_only__, 2, 3)); # else extern int __xpg_strerror_r (int __errnum, char *__buf, size_t __buflen) - __THROW __nonnull ((2)); + __THROW __nonnull ((2)) __attr_access ((__write_only__, 2, 3)); # define strerror_r __xpg_strerror_r # endif # else /* If a temporary buffer is required, at most BUFLEN bytes of BUF will be used. */ extern char *strerror_r (int __errnum, char *__buf, size_t __buflen) - __THROW __nonnull ((2)) __wur; + __THROW __nonnull ((2)) __wur __attr_access ((__write_only__, 2, 3)); # endif #endif @@ -433,7 +439,8 @@ extern char *strerror_l (int __errnum, locale_t __l) __THROW; /* Set N bytes of S to 0. The compiler will not delete a call to this function, even if S is dead after the call. */ -extern void explicit_bzero (void *__s, size_t __n) __THROW __nonnull ((1)); +extern void explicit_bzero (void *__s, size_t __n) __THROW __nonnull ((1)) + __attr_access ((__write_only__, 1, 2)); /* Return the next DELIM-delimited token from *STRINGP, terminating it with a '\0', and update *STRINGP to point past it. */ @@ -471,7 +478,8 @@ extern int strverscmp (const char *__s1, const char *__s2) extern char *strfry (char *__string) __THROW __nonnull ((1)); /* Frobnicate N bytes of S. */ -extern void *memfrob (void *__s, size_t __n) __THROW __nonnull ((1)); +extern void *memfrob (void *__s, size_t __n) __THROW __nonnull ((1)) + __attr_access ((__write_only__, 1, 2)); # ifndef basename /* Return the file name within directory of FILENAME. We don't