Changeset View
Standalone View
include/secure/_stdio.h
- This file was added.
/*- | |||||
* Copyright (c) 1990 The Regents of the University of California. | |||||
* All rights reserved. | |||||
* | |||||
* This code is derived from software contributed to Berkeley by | |||||
ngie: This seems out of order. Shouldn't the RCS tags be below the licensing text? | |||||
* Chris Torek. | |||||
* | |||||
* Redistribution and use in source and binary forms, with or without | |||||
* modification, are permitted provided that the following conditions | |||||
* are met: | |||||
* 1. Redistributions of source code must retain the above copyright | |||||
* notice, this list of conditions and the following disclaimer. | |||||
* 2. 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. | |||||
* 3. Neither the name of the University nor the names of its contributors | |||||
* may be used to endorse or promote products derived from this software | |||||
* without specific prior written permission. | |||||
* | |||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. | |||||
* | |||||
* @(#)stdio.h 5.17 (Berkeley) 6/3/91 | |||||
* $OpenBSD: stdio.h,v 1.35 2006/01/13 18:10:09 miod Exp $ | |||||
* $NetBSD: stdio.h,v 1.18 1996/04/25 18:29:21 jtc Exp $ | |||||
* bionic rev: 6cc98af72b0c48c58b2ab5fdb5f7abb842175299 | |||||
* $FreeBSD$ | |||||
*/ | |||||
#ifndef _STDIO_H_ | |||||
#error "You should not use <secure/_stdio.h> directly; include <stdio.h> instead." | |||||
#endif | |||||
#ifndef _SECURE_STDIO_H_ | |||||
#define _SECURE_STDIO_H_ | |||||
#include <secure/security.h> | |||||
#include <stdarg.h> | |||||
__BEGIN_DECLS | |||||
extern char *__fgets_chk(char *, int, FILE *, size_t); | |||||
extern char *__fgets_real(char *, int, FILE *) __RENAME(fgets); | |||||
__errordecl(__fgets_too_big_error, "fgets called with size bigger than buffer"); | |||||
__errordecl(__fgets_too_small_error, "fgets called with size less than zero"); | |||||
extern size_t __fread_chk(void * __restrict, size_t, size_t, FILE * __restrict, size_t); | |||||
extern size_t __fread_real(void * __restrict, size_t, size_t, FILE * __restrict) __RENAME(fread); | |||||
__errordecl(__fread_too_big_error, "fread called with size * count bigger than buffer"); | |||||
__errordecl(__fread_overflow, "fread called with overflowing size * count"); | |||||
extern size_t __fwrite_chk(const void * __restrict, size_t, size_t, FILE * __restrict, size_t); | |||||
Done Inline Actions/scratch/tmp/pfg/obj/mips.mips/scratch/tmp/pfg/head/tmp/usr/include/secure/_stdio.h:58: warning: redundant redeclaration of 'gets_real' pfg: /scratch/tmp/pfg/obj/mips.mips/scratch/tmp/pfg/head/tmp/usr/include/secure/_stdio.h:58: warning… | |||||
extern size_t __fwrite_real(const void * __restrict, size_t, size_t, FILE * __restrict) __RENAME(fwrite); | |||||
__errordecl(__fwrite_too_big_error, "fwrite called with size * count bigger than buffer"); | |||||
__errordecl(__fwrite_overflow, "fwrite called with overflowing size * count"); | |||||
extern int __sprintf_chk(char * __restrict, int, size_t, const char * __restrict, ...); | |||||
extern int __sprintf_real(char * __restrict, const char * __restrict, ...) __RENAME(sprintf); | |||||
extern int __vsprintf_chk(char * __restrict, int, size_t, const char * __restrict, __va_list); | |||||
extern int __vsprintf_real(char * __restrict, const char * __restrict, __va_list) __RENAME(vsprintf); | |||||
#if __ISO_C_VISIBLE >= 1999 | |||||
extern int __snprintf_chk(char * __restrict, size_t, int, size_t, const char * __restrict, ...); | |||||
extern int __snprintf_real(char * __restrict, size_t, const char * __restrict, ...) __RENAME(snprintf) __printflike(3, 4); | |||||
Done Inline Actions/scratch/tmp/pfg/obj/mips.mips/scratch/tmp/pfg/head/tmp/usr/include/secure/_stdio.h:69: warning: redundant redeclaration of 'snprintf_real' pfg: /scratch/tmp/pfg/obj/mips.mips/scratch/tmp/pfg/head/tmp/usr/include/secure/_stdio.h:69: warning… | |||||
extern int __vsnprintf_chk(char * __restrict, size_t, int, size_t, const char * __restrict, __va_list); | |||||
Done Inline Actions/scratch/tmp/pfg/obj/mips.mips/scratch/tmp/pfg/head/tmp/usr/include/secure/_stdio.h:70: warning: redundant redeclaration of 'vsnprintf_real' pfg: /scratch/tmp/pfg/obj/mips.mips/scratch/tmp/pfg/head/tmp/usr/include/secure/_stdio.h:70: warning… | |||||
extern int __vsnprintf_real(char * __restrict, size_t, const char * __restrict, __va_list) __RENAME(vsnprintf) __printflike(3, 0); | |||||
#endif | |||||
#ifdef __BSD_FORTIFY | |||||
#if __ISO_C_VISIBLE >= 1999 | |||||
__FORTIFY_INLINE __printflike(3, 0) int | |||||
vsnprintf(char *_dest, size_t _size, const char *_format, __va_list _ap) | |||||
{ | |||||
Not Done Inline ActionsYou'd have to ask the local C standard experts but I don't think declaring a standard function inline is standard compliant. What you should do instead is declare the function normally and then define a macro with the same name that performs the necessary checks. If you don't want to put too much code into the macro you can put it into a "static inline __always_inline" function instead and call this function from the macro. I think this will solve the problems you are seeing in some ports. tijl: You'd have to ask the local C standard experts but I don't think declaring a standard function… | |||||
size_t _bos = __bos(_dest); | |||||
#ifndef __clang__ | |||||
if (_bos == __FORTIFY_UNKNOWN_SIZE) | |||||
return (__vsnprintf_real(_dest, _size, _format, _ap)); | |||||
#endif | |||||
return (__vsnprintf_chk(_dest, _size, 0, _bos, _format, _ap)); | |||||
} | |||||
#endif /* __ISO_C_VISIBLE */ | |||||
__FORTIFY_INLINE __printflike(2, 0) int | |||||
vsprintf(char *_dest, const char *_format, __va_list _ap) | |||||
{ | |||||
Done Inline Actionsredundant clang check pfg: redundant clang check | |||||
size_t _bos = __bos(_dest); | |||||
#ifndef __clang__ | |||||
if (_bos == __FORTIFY_UNKNOWN_SIZE) | |||||
return (__vsprintf_real(_dest, _format, _ap)); | |||||
Done Inline Actions__has_builtin() || pfg: __has_builtin() || | |||||
Done Inline Actions#if !has_builtin(va_arg_pack) || defined(clang__) ? op: #if !__has_builtin(va_arg_pack) || defined(__clang__) ? | |||||
#endif | |||||
Done Inline ActionsWe only check has_builtin() in case clang implements something from the modern gcc, so it would be something like: pfg: We only check has_builtin() in case clang implements something from the modern gcc, so it would… | |||||
return (__vsprintf_chk(_dest, 0, _bos, _format, _ap)); | |||||
} | |||||
#if __ISO_C_VISIBLE >= 1999 | |||||
#if !__has_builtin(__builtin_va_arg_pack) && !__GNUC_PREREQ__(4, 3) /* defined(__clang__) */ | |||||
#if !defined(snprintf) && !defined(__cplusplus) | |||||
#define __wrap_snprintf(_dest, _size, ...) __snprintf_chk(_dest, _size, 0, __bos(_dest), __VA_ARGS__) | |||||
#define snprintf(...) __wrap_snprintf(__VA_ARGS__) | |||||
#endif /* !snprintf */ | |||||
#else /* __GNUC_PREREQ__(4, 3) */ | |||||
__FORTIFY_INLINE __printflike(3, 4) int | |||||
snprintf(char *_dest, size_t _size, const char *_format, ...) | |||||
{ | |||||
size_t _bos = __bos(_dest); | |||||
Done Inline Actions__builtin_va_arg_pack is only available in gcc 4.3+ pfg: __builtin_va_arg_pack is only available in gcc 4.3+ | |||||
if (_bos == __FORTIFY_UNKNOWN_SIZE) | |||||
return (__snprintf_real(_dest, _size, _format, | |||||
__builtin_va_arg_pack())); | |||||
Done Inline Actions__has_builtin() || pfg: __has_builtin() || | |||||
return (__snprintf_chk(_dest, _size, 0, _bos, _format, | |||||
__builtin_va_arg_pack())); | |||||
} | |||||
Done Inline ActionsRedundant clang check pfg: Redundant clang check | |||||
#endif /* !__GNUC_PREREQ__(4, 3) */ | |||||
#endif /* __ISO_C_VISIBLE */ | |||||
#if !__has_builtin(__builtin_va_arg_pack) && !__GNUC_PREREQ__(4, 3) /* defined(__clang__) */ | |||||
#if !defined(sprintf) && !defined(__cplusplus) | |||||
#define __wrap_sprintf(_dest, ...) __sprintf_chk(_dest, 0, __bos(_dest), __VA_ARGS__) | |||||
#define sprintf(...) __wrap_sprintf(__VA_ARGS__) | |||||
#endif /* !sprintf */ | |||||
#else /* __GNUC_PREREQ__(4, 3) */ | |||||
__FORTIFY_INLINE __printflike(2, 3) int | |||||
sprintf(char *_dest, const char *_format, ...) | |||||
{ | |||||
size_t _bos = __bos(_dest); | |||||
if (_bos == __FORTIFY_UNKNOWN_SIZE) | |||||
return (__sprintf_real(_dest, _format, | |||||
__builtin_va_arg_pack())); | |||||
return (__sprintf_chk(_dest, 0, _bos, _format, | |||||
__builtin_va_arg_pack())); | |||||
} | |||||
Done Inline Actions__builtin_va_arg_pack is only available on gcc >= 4.3 pfg: __builtin_va_arg_pack is only available on gcc >= 4.3 | |||||
#endif /* !__GNUC_PREREQ__(4, 3) */ | |||||
__FORTIFY_INLINE char * | |||||
fgets(char *_buf, int _n, FILE *_stream) | |||||
{ | |||||
size_t _bos = __bos(_buf); | |||||
#ifndef __clang__ | |||||
/* | |||||
* Compiler can prove, at compile time, that the passed in size | |||||
* is always negative. | |||||
* Force a compiler error. | |||||
*/ | |||||
if (__builtin_constant_p(_n) && (_n < 0)) | |||||
__fgets_too_small_error(); | |||||
/* | |||||
* Compiler doesn 't know destination size. | |||||
* Don' t call __fgets_chk. | |||||
*/ | |||||
if (_bos == __FORTIFY_UNKNOWN_SIZE) | |||||
return (__fgets_real(_buf, _n, _stream)); | |||||
/* | |||||
* Compiler can prove, at compile time, that the passed in size | |||||
* is always <= the actual object size. | |||||
* Don 't call __fgets_chk. | |||||
*/ | |||||
if (__builtin_constant_p(_n) && (_n <= (int)_bos)) | |||||
return (__fgets_real(_buf, _n, _stream)); | |||||
Done Inline ActionsThis should be _size pfg: This should be `_size` | |||||
/* | |||||
* Compiler can prove, at compile time, that the passed in size | |||||
* is always > the actual object size. | |||||
* Force a compiler error. | |||||
*/ | |||||
if (__builtin_constant_p(_n) && (_n > (int)_bos)) | |||||
__fgets_too_big_error(); | |||||
#endif | |||||
return (__fgets_chk(_buf, _n, _stream, _bos)); | |||||
} | |||||
__FORTIFY_INLINE size_t | |||||
fread(void * __restrict ptr, size_t size, size_t nmemb, FILE * __restrict stream) | |||||
{ | |||||
size_t bos = __bos0(ptr); | |||||
#ifndef __clang__ | |||||
pfgUnsubmitted Done Inline ActionsIt looks like we should also restrict this from some gcc versions. We are using __fread_too_big_error in this path but this causing linking erros with gcc 4.2. pfg: It looks like we should also restrict this from some gcc versions. We are using… | |||||
size_t total; | |||||
if (bos == __FORTIFY_UNKNOWN_SIZE) | |||||
return (__fread_real(ptr, size, nmemb, stream)); | |||||
if (__builtin_constant_p(size) && __builtin_constant_p(nmemb)) { | |||||
if (__size_mul_overflow(size, nmemb, &total)) | |||||
__fread_overflow(); | |||||
if (total > bos) | |||||
__fread_too_big_error(); | |||||
return (__fread_real(ptr, size, nmemb, stream)); | |||||
} | |||||
#endif | |||||
return (__fread_chk(ptr, size, nmemb, stream, bos)); | |||||
} | |||||
__FORTIFY_INLINE size_t | |||||
fwrite(const void * __restrict ptr, size_t size, size_t nmemb, FILE * __restrict stream) | |||||
{ | |||||
size_t bos = __bos0(ptr); | |||||
#ifndef __clang__ | |||||
size_t total; | |||||
if (bos == __FORTIFY_UNKNOWN_SIZE) | |||||
return __fwrite_real(ptr, size, nmemb, stream); | |||||
if (__builtin_constant_p(size) && __builtin_constant_p(nmemb)) { | |||||
if (__size_mul_overflow(size, nmemb, &total)) | |||||
__fwrite_overflow(); | |||||
if (total > bos) | |||||
__fwrite_too_big_error(); | |||||
return (__fwrite_real(ptr, size, nmemb, stream)); | |||||
} | |||||
#endif | |||||
return (__fwrite_chk(ptr, size, nmemb, stream, bos)); | |||||
} | |||||
#endif /* defined(__BSD_FORTIFY) */ | |||||
__END_DECLS | |||||
#endif /* !_SECURE_STDIO_H_ */ |
This seems out of order. Shouldn't the RCS tags be below the licensing text?