Changeset View
Standalone View
include/secure/_string.h
- This file was added.
/*- | |||||
* Copyright (c) 2015 Oliver Pinter | |||||
* Copyright (C) 2008 The Android Open Source Project | |||||
* All rights reserved. | |||||
* | |||||
* Redistribution and use in source and binary forms, with or without | |||||
* modification, are permitted provided that the following conditions | |||||
* are met: | |||||
* * Redistributions of source code must retain the above copyright | |||||
* notice, this list of conditions and the following disclaimer. | |||||
* * Redistributions in binary form must reproduce the above copyright | |||||
* notice, this list of conditions and the following disclaimer in | |||||
* the documentation and/or other materials provided with the | |||||
* distribution. | |||||
* | |||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS | |||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | |||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||||
* SUCH DAMAGE. | |||||
* | |||||
* bionic rev: 9ef26a3c4cd2e6d469f771815a07cb820800beb6 | |||||
* | |||||
* $FreeBSD$ | |||||
*/ | |||||
#ifndef _STRING_H_ | |||||
#error "You should not use <secure/string.h> directly; include <string.h> instead." | |||||
#endif | |||||
#ifndef _SECURE_STRING_H_ | |||||
#define _SECURE_STRING_H_ | |||||
#include <secure/security.h> | |||||
__BEGIN_DECLS | |||||
extern void *__memccpy_chk(void *, const void *, int, size_t, size_t); | |||||
extern void *__memccpy_real(void *, const void *, int, size_t) __RENAME(memccpy); | |||||
extern void *__memchr_chk(const void *, int, size_t, size_t); | |||||
extern void *__memchr_real(const void *, int, size_t) __RENAME(memchr); | |||||
__errordecl(__memchr_buf_size_error, "memchr called with size bigger than buffer"); | |||||
extern void *__memrchr_chk(const void *, int, size_t, size_t); | |||||
extern void *__memrchr_real(const void *, int, size_t) __RENAME(memrchr); | |||||
__errordecl(__memrchr_buf_size_error, "memrchr called with size bigger than buffer"); | |||||
extern char *__stpncpy_chk(char * __restrict, const char * __restrict, size_t, size_t); | |||||
extern char *__stpncpy_chk2(char * __restrict, const char * __restrict, size_t, size_t, size_t); | |||||
extern char *__strncpy_chk2(char * __restrict, const char * __restrict, size_t, size_t, size_t); | |||||
extern size_t __strlcpy_chk(char *, const char *, size_t, size_t); | |||||
extern size_t __strlcpy_real(char * __restrict, const char * __restrict, size_t) __RENAME(strlcpy); | |||||
extern size_t __strlcat_chk(char * __restrict, const char * __restrict, size_t, size_t); | |||||
extern size_t __strlcat_real(char * __restrict, const char * __restrict, size_t) __RENAME(strlcat); | |||||
extern size_t __strlen_chk(const char *, size_t); | |||||
extern size_t __strlen_real(const char *) __RENAME(strlen); | |||||
extern char *__strchr_chk(const char *, int, size_t); | |||||
extern char *__strchr_real(const char *, int) __RENAME(strchr); | |||||
extern char *__strchrnul_chk(const char *, int, size_t); | |||||
extern char *__strchrnul_real(const char *, int) __RENAME(strchrnul); | |||||
extern char *__strrchr_chk(const char *, int, size_t); | |||||
extern char *__strrchr_real(const char *, int) __RENAME(strrchr); | |||||
extern char *__rindex_chk(const char *, int, size_t); | |||||
extern char *__rindex_real(const char *, int) __RENAME(rindex); | |||||
#if defined(__BSD_FORTIFY) | |||||
#if __XSI_VISIBLE >= 600 | |||||
__FORTIFY_INLINE void * | |||||
memccpy(void * __restrict d, const void * __restrict s, int c, size_t n) | |||||
{ | |||||
size_t bos = __bos0(d); | |||||
if (bos == __FORTIFY_UNKNOWN_SIZE) | |||||
return (__memccpy_real(d, s, c, n)); | |||||
return (__memccpy_chk(d, s, c, n, bos)); | |||||
} | |||||
#endif /* __XSI_VISIBLE */ | |||||
__FORTIFY_INLINE void * | |||||
memchr(const void *s, int c, size_t n) | |||||
{ | |||||
size_t bos = __bos(s); | |||||
#if defined(__clang__) | |||||
if (bos == __FORTIFY_UNKNOWN_SIZE) | |||||
return (__memchr_real(s, c, n)); | |||||
#else | |||||
if (bos == __FORTIFY_UNKNOWN_SIZE) | |||||
return (__builtin_memchr(s, c, n)); | |||||
pfg: `__builtin_memchr` was added in gcc 4.3 | |||||
if (__builtin_constant_p(n) && (n > bos)) | |||||
__memchr_buf_size_error(); | |||||
if (__builtin_constant_p(n) && (n <= bos)) | |||||
return (__builtin_memchr(s, c, n)); | |||||
#endif | |||||
return (__memchr_chk(s, c, n, bos)); | |||||
} | |||||
#if __BSD_VISIBLE | |||||
__FORTIFY_INLINE void * | |||||
Done Inline ActionsI think this should be: However this should be causing trouble for gcc 4.2.1 (which doesn't have memchr_chk so #if has_builtin(memchr_chk) || GNUC_PREREQ__(4, 3) pfg: I think this should be:
#if !defined(__clang__) || __has_builtin(memchr_chk)
However this… | |||||
Done Inline ActionsWhy? I didn't see what you try to suggest here. __builtin___memchr_chk(...) function, there is only __memchr_chk call, which was implemented under lib/lib/secure/. op: Why? I didn't see what you try to suggest here.
There is no
```
__builtin___memchr_chk(...)… | |||||
Done Inline ActionsOK.. I am confused:
pfg: OK.. I am confused:
1) why aren't you running those checks for clang too it doesn't depend on… | |||||
Done Inline Actions
Btw, I have found about the builtin version of memchr_chk: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=37060 op: 1. I use the builtin versions only in __builting_varg_pack case and for the gcc's constant… | |||||
memrchr(const void *s, int c, size_t n) | |||||
{ | |||||
size_t bos = __bos(s); | |||||
if (bos == __FORTIFY_UNKNOWN_SIZE) | |||||
return (__memrchr_real(s, c, n)); | |||||
#if !defined(__clang__) | |||||
if (__builtin_constant_p(n) && (n > bos)) | |||||
(__memrchr_buf_size_error()); | |||||
if (__builtin_constant_p(n) && (n <= bos)) | |||||
return __memrchr_real(s, c, n); | |||||
#endif | |||||
return (__memrchr_chk(s, c, n, bos)); | |||||
} | |||||
#endif /* __BSD_VISIBLE */ | |||||
__FORTIFY_INLINE void * | |||||
memcpy(void * __restrict d, const void * __restrict s, size_t n) | |||||
{ | |||||
return (__builtin___memcpy_chk(d, s, n, __bos0(d))); | |||||
} | |||||
__FORTIFY_INLINE void * | |||||
memmove(void *d, const void *s, size_t l) | |||||
{ | |||||
return (__builtin___memmove_chk(d, s, l, __bos0(d))); | |||||
} | |||||
#if __POSIX_VISIBLE >= 200809 | |||||
__FORTIFY_INLINE char * | |||||
stpcpy(char* __restrict d, const char* __restrict s) | |||||
{ | |||||
return (__builtin___stpcpy_chk(d, s, __bos(d))); | |||||
} | |||||
#endif /* __POSIX_VISIBLE */ | |||||
__FORTIFY_INLINE char * | |||||
strcpy(char * __restrict d, const char * __restrict s) | |||||
{ | |||||
return (__builtin___strcpy_chk(d, s, __bos(d))); | |||||
} | |||||
#if __POSIX_VISIBLE >= 200809 | |||||
__FORTIFY_INLINE char * | |||||
stpncpy(char * __restrict d, const char * __restrict s, size_t n) | |||||
{ | |||||
size_t bos_dest = __bos(d); | |||||
size_t bos_src = __bos(s); | |||||
#if !defined(__clang__) | |||||
size_t slen; | |||||
#endif | |||||
Done Inline ActionsThis #endif is the next #if in line 179 probably bogus as clang doesn't have __builtin___stpncpy_chk AFAICT. pfg: This #endif is the next #if in line 179 probably bogus as clang doesn't have… | |||||
if (bos_src == __FORTIFY_UNKNOWN_SIZE) | |||||
return (__builtin___stpncpy_chk(d, s, n, bos_dest)); | |||||
Done Inline Actions__builtin___stpncpy_chk was introduced in gcc 4.8 pfg: `__builtin___stpncpy_chk` was introduced in gcc 4.8 | |||||
#if !defined(__clang__) | |||||
if (__builtin_constant_p(n) && (n <= bos_src)) | |||||
return (__builtin___stpncpy_chk(d, s, n, bos_dest)); | |||||
slen = __builtin_strlen(src); | |||||
pfgUnsubmitted Done Inline Actions/scratch/tmp/pfg/obj/powerpc.powerpc64/scratch/tmp/pfg/head/tmp/usr/include/secure/_string.h:183: error: 'src' undeclared (first use in this function) pfg: /scratch/tmp/pfg/obj/powerpc.powerpc64/scratch/tmp/pfg/head/tmp/usr/include/secure/_string.h… | |||||
if (__builtin_constant_p(slen)) | |||||
return (__builtin___stpncpy_chk(d, s, n, bos_dest)); | |||||
#endif | |||||
return (__stpncpy_chk2(d, s, n, bos_dest, bos_src)); | |||||
} | |||||
#endif /* __POSIX_VISIBLE */ | |||||
__FORTIFY_INLINE char * | |||||
strncpy(char * __restrict d, const char * __restrict s, size_t n) | |||||
{ | |||||
size_t bos_dest = __bos(d); | |||||
size_t bos_src = __bos(s); | |||||
#if !defined(__clang__) | |||||
size_t slen; | |||||
#endif | |||||
if (bos_src == __FORTIFY_UNKNOWN_SIZE) | |||||
return (__builtin___strncpy_chk(d, s, n, bos_dest)); | |||||
#if !defined(__clang__) | |||||
if (__builtin_constant_p(n) && (n <= bos_src)) | |||||
return (__builtin___strncpy_chk(d, s, n, bos_dest)); | |||||
slen = __builtin_strlen(s); | |||||
if (__builtin_constant_p(slen)) | |||||
return (__builtin___strncpy_chk(d, s, n, bos_dest)); | |||||
#endif | |||||
return (__strncpy_chk2(d, s, n, bos_dest, bos_src)); | |||||
} | |||||
__FORTIFY_INLINE char * | |||||
strcat(char * __restrict d, const char * __restrict s) | |||||
{ | |||||
return (__builtin___strcat_chk(d, s, __bos(d))); | |||||
} | |||||
__FORTIFY_INLINE char * | |||||
strncat(char * __restrict d, const char * __restrict s, size_t n) | |||||
{ | |||||
return (__builtin___strncat_chk(d, s, n, __bos(d))); | |||||
} | |||||
__FORTIFY_INLINE void * | |||||
memset(void *s, int c, size_t n) | |||||
{ | |||||
return (__builtin___memset_chk(s, c, n, __bos0(s))); | |||||
} | |||||
#if __BSD_VISIBLE | |||||
__FORTIFY_INLINE size_t | |||||
strlcpy(char * __restrict d, const char * __restrict s, size_t n) | |||||
{ | |||||
size_t bos = __bos(d); | |||||
/* Compiler doesn't know destination size. Don't call __strlcpy_chk */ | |||||
if (bos == __FORTIFY_UNKNOWN_SIZE) | |||||
return (__strlcpy_real(d, s, n)); | |||||
#if !defined(__clang__) | |||||
/* | |||||
* Compiler can prove, at compile time, that the passed in size | |||||
* is always <= the actual object size. Don't call __strlcpy_chk | |||||
*/ | |||||
if (__builtin_constant_p(n) && (n <= bos)) | |||||
return (__strlcpy_real(d, s, n)); | |||||
#endif | |||||
return (__strlcpy_chk(d, s, n, bos)); | |||||
} | |||||
#endif /* __BSD_VISIBLE */ | |||||
#if __BSD_VISIBLE | |||||
__FORTIFY_INLINE size_t | |||||
strlcat(char * __restrict d, const char * __restrict s, size_t n) | |||||
{ | |||||
size_t bos = __bos(d); | |||||
/* Compiler doesn't know destination size. Don't call __strlcat_chk */ | |||||
if (bos == __FORTIFY_UNKNOWN_SIZE) | |||||
return (__strlcat_real(d, s, n)); | |||||
#if !defined(__clang__) | |||||
/* | |||||
* Compiler can prove, at compile time, that the passed in size | |||||
* is always <= the actual object size. Don't call __strlcat_chk | |||||
*/ | |||||
if (__builtin_constant_p(n) && (n <= bos)) | |||||
return (__strlcat_real(d, s, n)); | |||||
#endif | |||||
Done Inline Actionserror: expected ';' before 'return' pfg: error: expected ';' before 'return' | |||||
return (__strlcat_chk(d, s, n, bos)); | |||||
} | |||||
#endif /* __BSD_VISIBLE */ | |||||
__FORTIFY_INLINE size_t | |||||
strlen(const char *s) | |||||
{ | |||||
size_t bos = __bos(s); | |||||
#if !defined(__clang__) | |||||
size_t slen; | |||||
#endif | |||||
#if defined(__clang__) | |||||
/* Compiler doesn't know destination size. Don't call __strlen_chk */ | |||||
if (bos == __FORTIFY_UNKNOWN_SIZE) | |||||
return (__strlen_real(s)); | |||||
#else | |||||
/* Compiler doesn't know destination size. Don't call __strlen_chk */ | |||||
if (bos == __FORTIFY_UNKNOWN_SIZE) | |||||
return (__builtin_strlen(s)); | |||||
slen = __builtin_strlen(s); | |||||
Not Done Inline ActionsFrom the net-p2p/namecoin port log (using clang and libc++): ... ^ /usr/include/secure/_string.h:306:1: note: previous definition is here (This builds with FORTIFY_SOURCE=2 enabled by the upstream sources). pfg: From the net-p2p/namecoin port log (using clang and libc++):
...
In file included from… | |||||
Not Done Inline ActionsThe strlcpy isn't a standard function, so we could disable them, when we building c++ programs or if only a small set of the ports failed, we should fix these ports instead. I just looked into namecoins source, and they reimplement unconditionally the strlcpy function, regardless of existing on the system or not, and blindly define BSD or BSD_VISIBLE on their headers. op: The strlcpy isn't a standard function, so we could disable them, when we building c++ programs… | |||||
Not Done Inline ActionsFORTIFY_SOURCE depends on the system headers being used. If only those are affected, it sounds like something that should be fixed in the port (and upstreamed). pfg: FORTIFY_SOURCE depends on the system headers being used.
Of course glibc has their doze of NIH… | |||||
if (__builtin_constant_p(slen)) | |||||
return (slen); | |||||
#endif | |||||
return (__strlen_chk(s, bos)); | |||||
} | |||||
__FORTIFY_INLINE char * | |||||
strchr(const char *s, int c) | |||||
{ | |||||
size_t bos = __bos(s); | |||||
#if !defined(__clang__) | |||||
size_t slen; | |||||
#endif | |||||
#if defined(__clang__) | |||||
/* Compiler doesn't know destination size. Don't call __strchr_chk */ | |||||
if (bos == __FORTIFY_UNKNOWN_SIZE) | |||||
return (__strchr_real(s, c)); | |||||
#else | |||||
/* Compiler doesn't know destination size. Don't call __strchr_chk */ | |||||
if (bos == __FORTIFY_UNKNOWN_SIZE) | |||||
return (__builtin_strchr(s, c)); | |||||
Not Done Inline ActionsFrom the net-p2p/namecoin port log (using clang and libc++): ^ /usr/include/secure/_string.h:330:1: note: previous definition is here pfg: From the net-p2p/namecoin port log (using clang and libc++):
...
In file included from… | |||||
Not Done Inline ActionsSame as the above. op: Same as the above. | |||||
slen = (__builtin_strlen(s)); | |||||
if (__builtin_constant_p(slen) && (slen < bos)) | |||||
return (__builtin_strchr(s, c)); | |||||
#endif | |||||
return (__strchr_chk(s, c, bos)); | |||||
} | |||||
__FORTIFY_INLINE char * | |||||
strchrnul(const char *s, int c) | |||||
{ | |||||
size_t bos = __bos(s); | |||||
/* Compiler doesn't know destination size. Don't call __strchr_chk */ | |||||
if (bos == __FORTIFY_UNKNOWN_SIZE) | |||||
return (__strchrnul_real(s, c)); | |||||
return (__strchrnul_chk(s, c, bos)); | |||||
} | |||||
__FORTIFY_INLINE char * | |||||
strrchr(const char *s, int c) | |||||
{ | |||||
size_t bos = __bos(s); | |||||
#if !defined(__clang__) | |||||
size_t slen; | |||||
#endif | |||||
#if defined(__clang__) | |||||
/* Compiler doesn't know destination size. Don't call __strrchr_chk */ | |||||
if (bos == __FORTIFY_UNKNOWN_SIZE) | |||||
return (__strrchr_real(s, c)); | |||||
#else | |||||
/* Compiler doesn't know destination size. Don't call __strrchr_chk */ | |||||
if (bos == __FORTIFY_UNKNOWN_SIZE) | |||||
return (__builtin_strrchr(s, c)); | |||||
slen = __builtin_strlen(s); | |||||
if (__builtin_constant_p(slen) && (slen < bos)) | |||||
return (__builtin_strrchr(s, c)); | |||||
#endif | |||||
return (__strrchr_chk(s, c, bos)); | |||||
} | |||||
__FORTIFY_INLINE char * | |||||
rindex(const char *s, int c) | |||||
{ | |||||
size_t bos = __bos(s); | |||||
#if !defined(__clang__) | |||||
size_t slen; | |||||
#endif | |||||
#if defined(__clang__) | |||||
/* Compiler doesn't know destination size. Don't call __strrchr_chk */ | |||||
if (bos == __FORTIFY_UNKNOWN_SIZE) | |||||
return (__rindex_real(s, c)); | |||||
#else | |||||
Done Inline Actionscc1: warnings being treated as errors from /scratch/tmp/pfg/head/sbin/rtsol/../../usr.sbin/rtsold/rtsol.c:63: /scratch/tmp/pfg/obj/mips.mips/scratch/tmp/pfg/head/tmp/usr/include/secure/_string.h:391: warning: no previous prototype for 'strchrnul' pfg: cc1: warnings being treated as errors
In file included from /scratch/tmp/pfg/obj/mips. | |||||
/* Compiler doesn't know destination size. Don't call __strrchr_chk */ | |||||
if (bos == __FORTIFY_UNKNOWN_SIZE) | |||||
return (__builtin_strrchr(s, c)); | |||||
slen = __builtin_strlen(s); | |||||
if (__builtin_constant_p(slen) && (slen < bos)) | |||||
return (__builtin_strrchr(s, c)); | |||||
#endif | |||||
return (__rindex_chk(s, c, bos)); | |||||
} | |||||
#endif /* defined(__BSD_FORTIFY) */ | |||||
__END_DECLS | |||||
#endif /* !_SECURE_STRING_H */ | |||||
Done Inline Actions/scratch/tmp/pfg/obj/mips.mips/scratch/tmp/pfg/head/tmp/usr/include/secure/_string.h:430: warning: no previous prototype for 'rindex' pfg: /scratch/tmp/pfg/obj/mips.mips/scratch/tmp/pfg/head/tmp/usr/include/secure/_string.h:430… |
__builtin_memchr was added in gcc 4.3