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); | |||||
extern void *__memcpy_chk(void *, const void *, size_t, size_t); | |||||
extern void *__memcpy_real(void *, const void *, size_t) __RENAME(memcpy); | |||||
__errordecl(__memchr_buf_size_error, "memchr called with size bigger than buffer"); | |||||
extern void * __memmove_chk(void *, const void *, size_t, size_t); | |||||
extern void * __memmove_real(void *, const void *, size_t) __RENAME(memmove); | |||||
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 void *__memset_chk(void *, int, size_t, size_t); | |||||
extern void *__memset_real(void *, int, size_t) __RENAME(memset); | |||||
extern char *__strcat_chk(char *__restrict, const char *__restrict, size_t); | |||||
extern char *__strcat_real(char *__restrict, const char *__restrict) __RENAME(strcat); | |||||
extern char *__strncat_chk(char *__restrict, const char *__restrict, size_t, size_t); | |||||
extern char *__strncat_real(char *__restrict, const char *__restrict, size_t) __RENAME(strncat); | |||||
extern char * __stpcpy_chk(char *, const char *, size_t); | |||||
extern char * __stpcpy_real(char *, const char *) __RENAME(stpcpy); | |||||
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 char *__strcpy_chk(char *, const char *, size_t); | |||||
extern char *__strcpy_real(char *, const char *) __RENAME(strcpy); | |||||
extern char *__strncpy_chk(char *, const char *, size_t, size_t); | |||||
extern char *__strncpy_real(char *, const char *, size_t) __RENAME(strncpy); | |||||
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)); | |||||
pfg: `__builtin_memchr` was added in gcc 4.3 | |||||
} | |||||
#endif /* __XSI_VISIBLE */ | |||||
__FORTIFY_INLINE void * | |||||
memchr(const void *_s, int _c, size_t _n) | |||||
{ | |||||
size_t _bos = __bos(_s); | |||||
if (_bos == __FORTIFY_UNKNOWN_SIZE) | |||||
return (__memchr_real(_s, _c, _n)); | |||||
#if !defined(__clang__) | |||||
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… | |||||
if (__builtin_constant_p(_n) && (_n > _bos)) | |||||
__memchr_buf_size_error(); | |||||
/* | |||||
* Compiler can prove, at compile time, that the passed in size | |||||
* is always <= the actual object size. Don't call __memchr_chk. | |||||
*/ | |||||
if (__builtin_constant_p(_n) && (_n <= _bos)) | |||||
return (__memchr_real(_s, _c, _n)); | |||||
#endif | |||||
return (__memchr_chk(_s, _c, _n, _bos)); | |||||
} | |||||
#if __BSD_VISIBLE | |||||
__FORTIFY_INLINE void * | |||||
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) | |||||
{ | |||||
size_t _bos = __bos0(_d); | |||||
if (_bos == __FORTIFY_UNKNOWN_SIZE) | |||||
return (__memcpy_real(_d, _s, _n)); | |||||
return (__memcpy_chk(_d, _s, _n, _bos)); | |||||
} | |||||
__FORTIFY_INLINE void * | |||||
memmove(void *_d, const void *_s, size_t _l) | |||||
{ | |||||
size_t _bos = __bos0(_d); | |||||
if (_bos == __FORTIFY_UNKNOWN_SIZE) | |||||
return (__memmove_real(_d, _s, _l)); | |||||
return (__memmove_chk(_d, _s, _l, _bos)); | |||||
} | |||||
#if __POSIX_VISIBLE >= 200809 | |||||
__FORTIFY_INLINE char * | |||||
stpcpy(char * __restrict _d, const char * __restrict _s) | |||||
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… | |||||
{ | |||||
size_t _bos = __bos(_d); | |||||
Done Inline Actions__builtin___stpncpy_chk was introduced in gcc 4.8 pfg: `__builtin___stpncpy_chk` was introduced in gcc 4.8 | |||||
if (_bos == __FORTIFY_UNKNOWN_SIZE) | |||||
return (__stpcpy_real(_d, _s)); | |||||
return (__stpcpy_chk(_d, _s, _bos)); | |||||
} | |||||
#endif /* __POSIX_VISIBLE */ | |||||
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… | |||||
__FORTIFY_INLINE char * | |||||
strcpy(char * __restrict _d, const char * __restrict _s) | |||||
{ | |||||
size_t _bos = __bos(_d); | |||||
if (_bos == __FORTIFY_UNKNOWN_SIZE) | |||||
return (__strcpy_real(_d, _s)); | |||||
return (__strcpy_chk(_d, _s, _bos)); | |||||
} | |||||
#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 | |||||
if (_bos_src == __FORTIFY_UNKNOWN_SIZE) | |||||
return (__stpncpy_chk(_d, _s, _n, _bos_dest)); | |||||
#if !defined(__clang__) | |||||
if (__builtin_constant_p(_n) && (_n <= _bos_src)) | |||||
return (__stpncpy_chk(_d, _s, _n, _bos_dest)); | |||||
_slen = __builtin_strlen(_s); | |||||
if (__builtin_constant_p(_slen)) | |||||
return (__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 (__strncpy_chk(_d, _s, _n, _bos_dest)); | |||||
#if !defined(__clang__) | |||||
if (__builtin_constant_p(_n) && (_n <= _bos_src)) | |||||
return (__strncpy_chk(_d, _s, _n, _bos_dest)); | |||||
_slen = __builtin_strlen(_s); | |||||
if (__builtin_constant_p(_slen)) | |||||
return (__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) | |||||
{ | |||||
size_t _bos = __bos(_d); | |||||
if (_bos == __FORTIFY_UNKNOWN_SIZE) | |||||
return (__strcat_real(_d, _s)); | |||||
return (__strcat_chk(_d, _s, _bos)); | |||||
} | |||||
__FORTIFY_INLINE char * | |||||
strncat(char * __restrict _d, const char * __restrict _s, size_t _n) | |||||
{ | |||||
size_t _bos = __bos(_d); | |||||
if (_bos == __FORTIFY_UNKNOWN_SIZE) | |||||
return (__strncat_real(_d, _s, _n)); | |||||
return (__strncat_chk(_d, _s, _n, _bos)); | |||||
} | |||||
__FORTIFY_INLINE void * | |||||
memset(void *_s, int _c, size_t _n) | |||||
{ | |||||
size_t _bos = __bos(_s); | |||||
if (_bos == __FORTIFY_UNKNOWN_SIZE) | |||||
return (__memset_real(_s, _c, _n)); | |||||
return (__memset_chk(_s, _c, _n, _bos)); | |||||
Done Inline Actionserror: expected ';' before 'return' pfg: error: expected ';' before 'return' | |||||
} | |||||
#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)); | |||||
} | |||||
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… | |||||
#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 | |||||
return (__strlcat_chk(_d, _s, _n, _bos)); | |||||
} | |||||
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. | |||||
#endif /* __BSD_VISIBLE */ | |||||
__FORTIFY_INLINE size_t | |||||
strlen(const char *_s) | |||||
{ | |||||
size_t _bos = __bos(_s); | |||||
#if !defined(__clang__) | |||||
size_t _slen; | |||||
#endif | |||||
/* Compiler doesn't know destination size. Don't call __strlen_chk. */ | |||||
if (_bos == __FORTIFY_UNKNOWN_SIZE) | |||||
return (__strlen_real(_s)); | |||||
#if !defined(__clang__) | |||||
_slen = __builtin_strlen(_s); // XXXOP __strlen_real? | |||||
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 | |||||
/* Compiler doesn't know destination size. Don't call __strchr_chk. */ | |||||
if (_bos == __FORTIFY_UNKNOWN_SIZE) | |||||
return (__strchr_real(_s, _c)); | |||||
#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. | |||||
*/ | |||||
_slen = (__builtin_strlen(_s)); | |||||
if (__builtin_constant_p(_slen) && (_slen < _bos)) | |||||
return (__strchr_real(_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)); | |||||
} | |||||
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. | |||||
__FORTIFY_INLINE char * | |||||
strrchr(const char *_s, int _c) | |||||
{ | |||||
size_t _bos = __bos(_s); | |||||
#if !defined(__clang__) | |||||
size_t _slen; | |||||
#endif | |||||
/* Compiler doesn't know destination size. Don't call __strrchr_chk. */ | |||||
if (_bos == __FORTIFY_UNKNOWN_SIZE) | |||||
return (__strrchr_real(_s, _c)); | |||||
#if !defined(__clang__) | |||||
/* | |||||
* Compiler can prove, at compile time, that the passed in size | |||||
* is always <= the actual object size. Don't call __strlen_chk. | |||||
*/ | |||||
_slen = __strlen_real(_s); | |||||
if (__builtin_constant_p(_slen) && (_slen < _bos)) | |||||
return (__strrchr_real(_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 | |||||
/* Compiler doesn't know destination size. Don't call __strrchr_chk. */ | |||||
if (_bos == __FORTIFY_UNKNOWN_SIZE) | |||||
return (__rindex_real(_s, _c)); | |||||
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… | |||||
#if !defined(__clang__) | |||||
/* | |||||
* Compiler can prove, at compile time, that the passed in size | |||||
* is always <= the actual object size. Don't call __rindex_chk. | |||||
*/ | |||||
_slen = __strlen_real(_s); | |||||
if (__builtin_constant_p(_slen) && (_slen < _bos)) | |||||
return (__rindex_real(_s, _c)); | |||||
#endif | |||||
return (__rindex_chk(_s, _c, _bos)); | |||||
} | |||||
#endif /* defined(__BSD_FORTIFY) */ | |||||
__END_DECLS | |||||
#endif /* !_SECURE_STRING_H */ |
__builtin_memchr was added in gcc 4.3