Add _FORTIFY_SOURCE support for string.h and stdio.h (#234)
This adds the fortified declarations, in line with the specifications within clang and the gcc documentation here: https://gcc.gnu.org/onlinedocs/gcc-6.3.0/gcc/Object-Size-Checking.html#Object-Size-Checking This simplifies the checks for fortify source, and makes the tests more robust. There is also the addition of a posix header, unistd.h, as a stopgap measure. Tested: Mac OS X, Linux, Windows.
This commit is contained in:
Родитель
261aacbce9
Коммит
f534fb22e8
|
@ -12,24 +12,47 @@
|
|||
|
||||
#include "_builtin_common.h"
|
||||
|
||||
#if _USE_FORTIFY_LEVEL > 0
|
||||
|
||||
#ifndef __has_builtin
|
||||
#define _undef__has_builtin
|
||||
#define __has_builtin(x) 0
|
||||
#endif
|
||||
|
||||
#if __has_builtin(__builtin___snprintf_chk) || defined(__GNUC__)
|
||||
|
||||
#if __has_builtin(__builtin___sprintf_chk) || defined(__GNUC__)
|
||||
// sprintf
|
||||
extern _Unchecked
|
||||
int __snprintf_chk(char * __restrict s : count(n),
|
||||
size_t n,
|
||||
int flag,
|
||||
size_t obj_size,
|
||||
const char * __restrict format :
|
||||
itype(restrict _Nt_array_ptr<const char>),
|
||||
...);
|
||||
int __sprintf_chk(char * restrict buffer : itype(restrict _Nt_array_ptr<char>),
|
||||
int flag,
|
||||
size_t obj_size,
|
||||
const char * restrict format :
|
||||
itype(restrict _Nt_array_ptr<const char>),
|
||||
...);
|
||||
|
||||
_Unchecked
|
||||
int __builtin___snprintf_chk(char * restrict s : count(n),
|
||||
size_t n,
|
||||
int __builtin___sprintf_chk(char * restrict buffer : itype(restrict _Nt_array_ptr<char>),
|
||||
int flag,
|
||||
size_t obj_size,
|
||||
const char * restrict format :
|
||||
itype(restrict _Nt_array_ptr<const char>),
|
||||
...);
|
||||
#endif
|
||||
|
||||
#if __has_builtin(__builtin___snprintf_chk) || defined(__GNUC__)
|
||||
// snprintf
|
||||
extern _Unchecked
|
||||
int __snprintf_chk(char * restrict buffer : count(maxlen),
|
||||
size_t maxlen,
|
||||
int flag,
|
||||
size_t obj_size,
|
||||
const char * restrict format :
|
||||
itype(restrict _Nt_array_ptr<const char>),
|
||||
...);
|
||||
|
||||
_Unchecked
|
||||
int __builtin___snprintf_chk(char * restrict buffer : count(maxlen),
|
||||
size_t maxlen,
|
||||
int flag,
|
||||
size_t obj_size,
|
||||
const char * restrict format :
|
||||
|
@ -38,20 +61,41 @@ int __builtin___snprintf_chk(char * restrict s : count(n),
|
|||
...);
|
||||
#endif
|
||||
|
||||
|
||||
#if __has_builtin(__builtin___vsnprintf_chk) || defined(__GNUC__)
|
||||
#if __has_builtin(__builtin___vsprintf_chk) || defined(__GNUC__)
|
||||
// vsprintf
|
||||
extern _Unchecked
|
||||
int __vsnprintf_chk(char * __restrict s : count(n),
|
||||
size_t n,
|
||||
int flag,
|
||||
size_t obj_size,
|
||||
const char * __restrict format :
|
||||
itype(restrict _Nt_array_ptr<const char>),
|
||||
va_list);
|
||||
int __vsprintf_chk(char * restrict buffer : itype(restrict _Nt_array_ptr<char>),
|
||||
int flag,
|
||||
size_t obj_size,
|
||||
const char * restrict format :
|
||||
itype(restrict _Nt_array_ptr<const char>),
|
||||
va_list);
|
||||
|
||||
|
||||
_Unchecked
|
||||
int __builtin___vsnprintf_chk(char * restrict s : count(n),
|
||||
size_t n,
|
||||
int __builtin___vsprintf_chk(char * restrict buffer : itype(restrict _Nt_array_ptr<char>),
|
||||
int flag,
|
||||
size_t obj_size,
|
||||
const char * restrict format :
|
||||
itype(restrict _Nt_array_ptr<const char>),
|
||||
va_list arg);
|
||||
#endif
|
||||
|
||||
|
||||
#if __has_builtin(__builtin___vsnprintf_chk) || defined(__GNUC__)
|
||||
// vsnprintf
|
||||
extern _Unchecked
|
||||
int __vsnprintf_chk(char * restrict buffer : count(maxlen),
|
||||
size_t maxlen,
|
||||
int flag,
|
||||
size_t obj_size,
|
||||
const char * restrict format :
|
||||
itype(restrict _Nt_array_ptr<const char>),
|
||||
va_list);
|
||||
|
||||
_Unchecked
|
||||
int __builtin___vsnprintf_chk(char * restrict buffer : count(maxlen),
|
||||
size_t maxlen,
|
||||
int flag,
|
||||
size_t obj_size,
|
||||
const char * restrict format :
|
||||
|
@ -59,7 +103,73 @@ int __builtin___vsnprintf_chk(char * restrict s : count(n),
|
|||
va_list arg);
|
||||
#endif
|
||||
|
||||
#if __has_builtin(__builtin___fprintf_chk) || defined(__GNUC__)
|
||||
// fprintf
|
||||
extern _Unchecked
|
||||
int __fprintf_chk(FILE * restrict stream : itype(restrict _Ptr<FILE>),
|
||||
int flag,
|
||||
const char * restrict format :
|
||||
itype(restrict _Nt_array_ptr<const char>),
|
||||
...);
|
||||
|
||||
_Unchecked
|
||||
int __builtin___fprintf_chk(FILE * restrict stream : itype(restrict _Ptr<FILE>),
|
||||
int flag,
|
||||
const char * restrict format :
|
||||
itype(restrict _Nt_array_ptr<const char>),
|
||||
...);
|
||||
#endif
|
||||
|
||||
#if __has_builtin(__builtin___printf_chk) || defined(__GNUC__)
|
||||
// printf
|
||||
extern _Unchecked
|
||||
int __printf_chk(int flag,
|
||||
const char * restrict format :
|
||||
itype(restrict _Nt_array_ptr<const char>),
|
||||
...);
|
||||
|
||||
_Unchecked
|
||||
int __builtin___printf_chk(int flag,
|
||||
const char * restrict format :
|
||||
itype(restrict _Nt_array_ptr<const char>),
|
||||
...);
|
||||
#endif
|
||||
|
||||
#if __has_builtin(__builtin___vfprintf_chk) || defined(__GNUC__)
|
||||
// vfprintf
|
||||
extern _Unchecked
|
||||
int __vfprintf_chk(FILE * restrict stream : itype(restrict _Ptr<FILE>),
|
||||
int flag,
|
||||
const char * restrict format :
|
||||
itype(restrict _Nt_array_ptr<const char>),
|
||||
va_list);
|
||||
|
||||
_Unchecked
|
||||
int __builtin___vfprintf_chk(FILE * restrict stream : itype(restrict _Ptr<FILE>),
|
||||
int flag,
|
||||
const char * restrict format :
|
||||
itype(restrict _Nt_array_ptr<const char>),
|
||||
va_list);
|
||||
#endif
|
||||
|
||||
#if __has_builtin(__builtin___vprintf_chk) || defined(__GNUC__)
|
||||
// vprintf
|
||||
extern _Unchecked
|
||||
int __vprintf_chk(int flag,
|
||||
const char * restrict format :
|
||||
itype(restrict _Nt_array_ptr<const char>),
|
||||
va_list);
|
||||
|
||||
_Unchecked
|
||||
int __builtin___vprintf_chk(int flag,
|
||||
const char * restrict format :
|
||||
itype(restrict _Nt_array_ptr<const char>),
|
||||
va_list);
|
||||
#endif
|
||||
|
||||
#ifdef _undef__has_builtin
|
||||
#undef _undef__has_builtin
|
||||
#undef __has_builtin
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
|
||||
#include "_builtin_common.h"
|
||||
|
||||
#if _USE_FORTIFY_LEVEL > 0
|
||||
|
||||
#ifndef __has_builtin
|
||||
#define _undef__has_builtin
|
||||
#define __has_builtin(x) 0
|
||||
|
@ -38,6 +40,24 @@ void *__builtin___memset_chk(void * s : byte_count(n),
|
|||
size_t obj_size) : bounds(s, (_Array_ptr<char>) s + n);
|
||||
#endif
|
||||
|
||||
#if __has_builtin(__builtin___strcat_chk) || defined(__GNUC__)
|
||||
// Left Unchecked Intentionally. See comment in string_checked.h
|
||||
_Unchecked
|
||||
char *__builtin___strcat_chk(char * restrict dest,
|
||||
const char * restrict src :
|
||||
itype(restrict _Nt_array_ptr<const char>),
|
||||
size_t obj_size);
|
||||
#endif
|
||||
|
||||
#if __has_builtin(__builtin___strcpy_chk) || defined(__GNUC__)
|
||||
// Left Unchecked Intentionally. See comment in string_checked.h
|
||||
_Unchecked
|
||||
char *__builtin___strcpy_chk(char * restrict dest,
|
||||
const char * restrict src :
|
||||
itype(restrict _Nt_array_ptr<const char>),
|
||||
size_t obj_size);
|
||||
#endif
|
||||
|
||||
#if __has_builtin(__builtin___strncat_chk) || defined(__GNUC__)
|
||||
// TODO: we have no way to express the bounds requirement on dest,
|
||||
// which needs to be count(strlen(dest) + n).
|
||||
|
@ -59,3 +79,5 @@ char *__builtin___strncpy_chk(char * restrict dest : count(n),
|
|||
#undef _undef__has_builtin
|
||||
#undef __has_builtin
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -50,60 +50,74 @@ int setvbuf(FILE * restrict stream : itype(restrict _Ptr<FILE>),
|
|||
// * Any pointer arguments may not meet the requirements of the
|
||||
// format string.
|
||||
//
|
||||
#if _FORTIFY_SOURCE == 0
|
||||
_Unchecked
|
||||
int fprintf(FILE * restrict stream : itype(restrict _Ptr<FILE>),
|
||||
const char * restrict format : itype(restrict _Nt_array_ptr<const char>), ...);
|
||||
#endif
|
||||
|
||||
_Unchecked
|
||||
int fscanf(FILE * restrict stream : itype(restrict _Ptr<FILE>),
|
||||
const char * restrict format : itype(restrict _Nt_array_ptr<const char>), ...);
|
||||
|
||||
#if _FORTIFY_SOURCE == 0
|
||||
_Unchecked
|
||||
int printf(const char * restrict format : itype(restrict _Nt_array_ptr<const char>), ...);
|
||||
#endif
|
||||
|
||||
_Unchecked
|
||||
int scanf(const char * restrict format : itype(restrict _Nt_array_ptr<const char>), ...);
|
||||
|
||||
#if _FORTIFY_SOURCE == 0
|
||||
// The output buffer parameter s is an unchecked pointer because no bounds are provided.
|
||||
_Unchecked
|
||||
int sprintf(char * restrict s,
|
||||
const char * restrict format : itype(restrict _Nt_array_ptr<const char>), ...);
|
||||
#endif
|
||||
|
||||
_Unchecked
|
||||
int sscanf(const char * restrict s : itype(restrict _Nt_array_ptr<const char>),
|
||||
const char * restrict format : itype(restrict _Nt_array_ptr<const char>), ...);
|
||||
// TODO: Apple System Headers Support
|
||||
#if !defined (__APPLE__) && _FORTIFY_SOURCE > 0
|
||||
|
||||
#if _FORTIFY_SOURCE == 0
|
||||
_Unchecked
|
||||
int snprintf(char * restrict s : count(n), size_t n,
|
||||
const char * restrict format : itype(restrict _Nt_array_ptr<const char>), ...);
|
||||
#endif
|
||||
|
||||
_Unchecked
|
||||
int vfprintf(FILE * restrict stream : itype(restrict _Ptr<FILE>),
|
||||
const char * restrict format : itype(restrict _Nt_array_ptr<const char>),
|
||||
va_list arg);
|
||||
#endif
|
||||
|
||||
_Unchecked
|
||||
int vfscanf(FILE * restrict stream : itype(restrict _Ptr<FILE>),
|
||||
const char * restrict format : itype(restrict _Nt_array_ptr<const char>),
|
||||
va_list arg);
|
||||
|
||||
#if _FORTIFY_SOURCE == 0
|
||||
_Unchecked
|
||||
int vprintf(const char * restrict format : itype(restrict _Nt_array_ptr<const char>),
|
||||
va_list arg);
|
||||
#endif
|
||||
|
||||
_Unchecked
|
||||
int vscanf(const char * restrict format : itype(restrict _Nt_array_ptr<const char>),
|
||||
va_list arg);
|
||||
// TODO: Apple System Headers Support
|
||||
#if !defined (__APPLE__) && _FORTIFY_SOURCE > 0
|
||||
|
||||
#if _FORTIFY_SOURCE == 0
|
||||
_Unchecked
|
||||
int vsnprintf(char * restrict s : count(n), size_t n,
|
||||
const char * restrict format,
|
||||
va_list arg);
|
||||
#endif
|
||||
|
||||
// The output buffer parameter has an unchecked pointer type becuse it is missing bounds.
|
||||
_Unchecked
|
||||
int vsprintf(char * restrict s,
|
||||
const char * restrict format : itype(restrict _Nt_array_ptr<const char>),
|
||||
va_list arg);
|
||||
#endif
|
||||
|
||||
_Unchecked
|
||||
int vsscanf(const char * restrict s : itype(restrict _Nt_array_ptr<const char>),
|
||||
const char * restrict format : itype(restrict _Nt_array_ptr<const char>),
|
||||
|
|
|
@ -35,8 +35,7 @@
|
|||
#undef strspn
|
||||
#endif
|
||||
|
||||
// TODO: Apple System Headers Support
|
||||
#if !( defined(__APPLE__) && _FORTIFY_SOURCE > 0)
|
||||
#if _FORTIFY_SOURCE == 0
|
||||
void *memcpy(void * restrict dest : byte_count(n),
|
||||
const void * restrict src : byte_count(n),
|
||||
size_t n) : bounds(dest, (_Array_ptr<char>) dest + n);
|
||||
|
@ -44,20 +43,21 @@ void *memcpy(void * restrict dest : byte_count(n),
|
|||
void *memmove(void * restrict dest : byte_count(n),
|
||||
const void * restrict src : byte_count(n),
|
||||
size_t n) : bounds(dest, (_Array_ptr<char>)dest + n);
|
||||
#endif
|
||||
|
||||
void *memset(void * dest : byte_count(n),
|
||||
int c,
|
||||
size_t n) : bounds(dest, (_Array_ptr<char>)dest + n);
|
||||
|
||||
// Dest is left unchecked intentionally. There is no bound on dest, so this
|
||||
// is always an unchecked function
|
||||
_Unchecked
|
||||
char *strcpy(char * restrict s1,
|
||||
const char * restrict s2 : itype(restrict _Nt_array_ptr<const char>));
|
||||
char *strcpy(char * restrict dest,
|
||||
const char * restrict src : itype(restrict _Nt_array_ptr<const char>));
|
||||
|
||||
|
||||
// TODO: Apple System Headers Support
|
||||
#if !( defined(__APPLE__) && _FORTIFY_SOURCE > 0)
|
||||
char *strncpy(char * restrict dest : count(n),
|
||||
const char * restrict src : count(n),
|
||||
size_t n) : bounds(dest, (_Array_ptr<char>)dest + n);
|
||||
#endif
|
||||
|
||||
// Dest is left unchecked intentionally. There is no bound on dest, so this
|
||||
// is always an unchecked function.
|
||||
|
@ -65,8 +65,6 @@ _Unchecked
|
|||
char *strcat(char * restrict dest,
|
||||
const char * restrict src : itype(restrict _Nt_array_ptr<const char>));
|
||||
|
||||
// TODO: Apple System Headers Support
|
||||
#if !( defined(__APPLE__) && _FORTIFY_SOURCE > 0)
|
||||
// TODO: we have no way to express the bounds requirement on dest,
|
||||
// which needs to be count(strlen(dest) + n).
|
||||
_Unchecked
|
||||
|
@ -114,12 +112,6 @@ char *strtok(char * restrict s1 : itype(restrict _Nt_array_ptr<char>),
|
|||
const char * restrict s2 : itype(restrict _Nt_array_ptr<const char>)) :
|
||||
itype(_Nt_array_ptr<char>);
|
||||
|
||||
// TODO: Apple System Headers Support
|
||||
#if !( defined(__APPLE__) && _FORTIFY_SOURCE > 0)
|
||||
void *memset(void *s : byte_count(n), int c, size_t n) :
|
||||
bounds(s, (_Array_ptr<char>) s + n);
|
||||
#endif
|
||||
|
||||
char *strerror(int errnum) : itype(_Nt_array_ptr<char>);
|
||||
size_t strlen(const char *s : itype(_Nt_array_ptr<const char>));
|
||||
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
//---------------------------------------------------------------------//
|
||||
// Bounds-safe interfaces for functions in unistd.h that //
|
||||
// take pointer arguments. //
|
||||
// //
|
||||
// These are POSIX-only //
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#pragma BOUNDS_CHECKED ON
|
||||
|
||||
#if _POSIX_VERSION >= 200112L
|
||||
|
||||
extern char ** environ : itype(_Nt_array_ptr<_Nt_array_ptr<char>>);
|
||||
|
||||
#endif
|
||||
|
||||
#pragma BOUNDS_CHECKED OFF
|
|
@ -4,7 +4,11 @@
|
|||
// The following lines are for the LLVM test harness:
|
||||
//
|
||||
// RUN: %clang -fcheckedc-extension -fsyntax-only %s
|
||||
// RUN: %clang -fcheckedc-extension -fsyntax-only -D_FORTIFY_SOURCE=0 %s
|
||||
// RUN: %clang -fcheckedc-extension -fsyntax-only -D_FORTIFY_SOURCE=1 %s
|
||||
// RUN: %clang -fcheckedc-extension -fsyntax-only -D_FORTIFY_SOURCE=2 %s
|
||||
|
||||
// C Standard
|
||||
#include "../../include/fenv_checked.h"
|
||||
#include "../../include/inttypes_checked.h"
|
||||
#include "../../include/math_checked.h"
|
||||
|
@ -15,3 +19,15 @@
|
|||
#define _CHECKEDC_MOCKUP_THREADS 1
|
||||
#include "../../include/threads_checked.h"
|
||||
#include "../../include/time_checked.h"
|
||||
|
||||
// Posix Headers
|
||||
//
|
||||
// Uses clang-specific __has_include macro to detect unistd.h
|
||||
// which is required by Posix Standard.
|
||||
#if defined(__has_include)
|
||||
#if __has_include(<unistd.h>)
|
||||
|
||||
#include "../../include/unistd_checked.h"
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
Загрузка…
Ссылка в новой задаче