Index: include/secure/Makefile =================================================================== --- include/secure/Makefile +++ include/secure/Makefile @@ -1,6 +1,6 @@ # $FreeBSD$ -INCS= security.h _poll.h _socket.h _stat.h +INCS= security.h _poll.h _socket.h _stat.h _stdio.h INCSDIR= ${INCLUDEDIR}/secure .include Index: include/secure/_stdio.h =================================================================== --- /dev/null +++ include/secure/_stdio.h @@ -0,0 +1,240 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * 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 directly; include instead." +#endif + +#ifndef _SECURE_STDIO_H_ +#define _SECURE_STDIO_H_ + +#include +#include + +__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); +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); +extern int __vsnprintf_chk(char * __restrict, size_t, int, size_t, const char * __restrict, __va_list); +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) +{ + 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) +{ + size_t _bos = __bos(_dest); + +#ifndef __clang__ + if (_bos == __FORTIFY_UNKNOWN_SIZE) + return (__vsprintf_real(_dest, _format, _ap)); +#endif + + 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); + + if (_bos == __FORTIFY_UNKNOWN_SIZE) + return (__snprintf_real(_dest, _size, _format, + __builtin_va_arg_pack())); + + return (__snprintf_chk(_dest, _size, 0, _bos, _format, + __builtin_va_arg_pack())); +} +#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())); +} + +#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)); + /* + * 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__ + 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_ */ Index: include/stdio.h =================================================================== --- include/stdio.h +++ include/stdio.h @@ -521,4 +521,9 @@ #endif /* __cplusplus */ __END_DECLS + +#if defined(__BSD_FORTIFY) +#include +#endif + #endif /* !_STDIO_H_ */ Index: lib/libc/secure/Makefile.inc =================================================================== --- lib/libc/secure/Makefile.inc +++ lib/libc/secure/Makefile.inc @@ -12,7 +12,12 @@ stack_protector_compat.c # Sources which contains FORTIFY_SOURCE functions: -#SRCS+= +SRCS+= \ + __fgets_chk.c \ + __fread_chk.c \ + __fwrite_chk.c \ + __vsnprintf_chk.c \ + __vsprintf_chk.c # Sources which contains FORTIFY_SOURCE functions, # but live in .h files under sys/sys Index: lib/libc/secure/Symbol.map =================================================================== --- lib/libc/secure/Symbol.map +++ lib/libc/secure/Symbol.map @@ -18,11 +18,18 @@ }; FBSD_1.4 { + __fgets_chk; __fortify_chk_fail; + __fread_chk; + __fwrite_chk; __poll_chk; __ppoll_chk; __recvfrom_chk; + __snprintf_chk; + __sprintf_chk; __umask_chk; + __vsnprintf_chk; + __vsprintf_chk; __secure_fail; }; Index: lib/libc/secure/__fgets_chk.c =================================================================== --- /dev/null +++ lib/libc/secure/__fgets_chk.c @@ -0,0 +1,55 @@ +/*- + * Copyright (C) 2012 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: 6cc98af72b0c48c58b2ab5fdb5f7abb842175299 + * + * $FreeBSD$ + */ + +#undef _FORTIFY_SOURCE + +#include +#include +#include +#include +#include "secure/_stdio.h" + +char * +__fgets_chk(char *buf, int n, FILE *stream, size_t bos) +{ + + if (bos == __FORTIFY_UNKNOWN_SIZE) + return (fgets(buf, n, stream)); + + if (n < 0) + __fortify_chk_fail("fgets: buffer size < 0"); + + if (((size_t)n) > bos) + __fortify_chk_fail("fgets: prevented write past end of buffer"); + + return (fgets(buf, n, stream)); +} Index: lib/libc/secure/__fread_chk.c =================================================================== --- /dev/null +++ lib/libc/secure/__fread_chk.c @@ -0,0 +1,56 @@ +/*- + * Copyright (C) 2015 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: fed2659869ec41a93f655be8058568ddab419e01 + * + * $FreeBSD$ + */ + +#undef _FORTIFY_SOURCE + +#include +#include +#include +#include "secure/_stdio.h" + +size_t +__fread_chk(void *__restrict ptr, size_t size, size_t nmemb, FILE * __restrict stream, size_t bos) +{ + size_t total; + + if (__predict_false(bos == __FORTIFY_UNKNOWN_SIZE)) + return (fread(ptr, size, nmemb, stream)); + + if (__predict_false(__size_mul_overflow(size, nmemb, &total))) { + //overflow: trigger the error path in fread + return (fread(ptr, size, nmemb, stream)); + } + if (__predict_false(total > bos)) + __fortify_chk_fail("fread: prevented write past end of buffer"); + + return (fread(ptr, size, nmemb, stream)); +} Index: lib/libc/secure/__fwrite_chk.c =================================================================== --- /dev/null +++ lib/libc/secure/__fwrite_chk.c @@ -0,0 +1,57 @@ +/*- + * Copyright (C) 2015 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: fed2659869ec41a93f655be8058568ddab419e01 + * + * $FreeBSD$ + */ + +#undef _FORTIFY_SOURCE + +#include +#include +#include +#include "secure/_stdio.h" + +size_t +__fwrite_chk(const void * __restrict ptr, size_t size, size_t nmemb, FILE * __restrict stream, size_t bos) +{ + size_t total; + + if (__predict_false(bos == __FORTIFY_UNKNOWN_SIZE)) + return (fwrite(ptr, size, nmemb, stream)); + + if (__predict_false(__size_mul_overflow(size, nmemb, &total))) { + // overflow: trigger the error path in fwrite + return (fwrite(ptr, size, nmemb, stream)); + } + + if (__predict_false(total > bos)) + __fortify_chk_fail("fwrite: prevented read past end of buffer"); + + return (fwrite(ptr, size, nmemb, stream)); +} Index: lib/libc/secure/__vsnprintf_chk.c =================================================================== --- /dev/null +++ lib/libc/secure/__vsnprintf_chk.c @@ -0,0 +1,76 @@ +/*- + * Copyright (C) 2012 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: d807b9a12d3e49132b095df3d883618452033b51 + * + * $FreeBSD$ + */ + +#undef _FORTIFY_SOURCE + +#include +#include +#include +#include +#include +#include "secure/_stdio.h" + +int +__vsnprintf_chk(char *d, size_t n, int flags, size_t bos, const char *fmt, va_list va) +{ + + if (__predict_false(bos == __FORTIFY_UNKNOWN_SIZE)) + return (vsnprintf(d, n, fmt, va)); + + if (__predict_false(n > bos)) + __fortify_chk_fail( + "vsnprintf: prevented write past end of buffer"); + + return (vsnprintf(d, n, fmt, va)); +} + + +int +__snprintf_chk(char *d, size_t n, int flags, size_t bos, const char *fmt, ...) +{ + va_list va; + int result; + + if (bos == __FORTIFY_UNKNOWN_SIZE) { + va_start(va, fmt); + result = vsnprintf(d, n, fmt, va); + va_end(va); + + return (result); + } + + va_start(va, fmt); + result = __vsnprintf_chk(d, n, flags, bos, fmt, va); + va_end(va); + + return (result); +} Index: lib/libc/secure/__vsprintf_chk.c =================================================================== --- /dev/null +++ lib/libc/secure/__vsprintf_chk.c @@ -0,0 +1,78 @@ +/*- + * Copyright (C) 2012 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: d807b9a12d3e49132b095df3d883618452033b51 + * + * $FreeBSD$ + */ + +#undef _FORTIFY_SOURCE + +#include +#include +#include +#include +#include +#include "secure/_stdio.h" + +int +__vsprintf_chk(char * __restrict d, int flags, size_t bos, const char * __restrict fmt, __va_list va) +{ + int result; + + if (__predict_false(bos == __FORTIFY_UNKNOWN_SIZE)) + return (vsprintf(d, fmt, va)); + + result = vsnprintf(d, bos, fmt, va); + if ((size_t)result >= bos) + __fortify_chk_fail( + "vsprintf: prevented write past end of buffer"); + + return (result); +} + + +int +__sprintf_chk(char * __restrict d, int flags, size_t bos, const char * __restrict fmt, ...) +{ + va_list va; + int result; + + if (bos == __FORTIFY_UNKNOWN_SIZE) { + va_start(va, fmt); + result = vsprintf(d, fmt, va); + va_end(va); + + return (result); + } + + va_start(va, fmt); + result = __vsprintf_chk(d, flags, bos, fmt, va); + va_end(va); + + return (result); +}