Index: include/stdio.h =================================================================== --- include/stdio.h +++ include/stdio.h @@ -49,6 +49,11 @@ #define _SIZE_T_DECLARED #endif +#ifndef _RSIZE_T_DEFINED +#define _RSIZE_T_DEFINED +typedef size_t rsize_t; +#endif + #if __POSIX_VISIBLE >= 200809 #ifndef _OFF_T_DECLARED #define _OFF_T_DECLARED @@ -263,6 +268,9 @@ int getc(FILE *); int getchar(void); char *gets(char *); +#if defined(__EXT1_VISIBLE) && __EXT1_VISIBLE == 1 +char *gets_s(char *, rsize_t); +#endif void perror(const char *); int printf(const char * __restrict, ...); int putc(int, FILE *); Index: lib/libc/stdio/Makefile.inc =================================================================== --- lib/libc/stdio/Makefile.inc +++ lib/libc/stdio/Makefile.inc @@ -14,7 +14,7 @@ fputwc.c fputws.c fread.c freopen.c fscanf.c fseek.c fsetpos.c \ ftell.c funopen.c fvwrite.c fwalk.c fwide.c fwprintf.c fwscanf.c \ fwrite.c getc.c getchar.c getdelim.c getline.c \ - gets.c getw.c getwc.c getwchar.c makebuf.c mktemp.c \ + gets.c gets_s.c getw.c getwc.c getwchar.c makebuf.c mktemp.c \ open_memstream.c open_wmemstream.c \ perror.c printf.c printf-pos.c putc.c putchar.c \ puts.c putw.c putwc.c putwchar.c \ @@ -50,6 +50,7 @@ ferror.3 fileno.3 ferror.3 fileno_unlocked.3 MLINKS+=fflush.3 fpurge.3 MLINKS+=fgets.3 gets.3 +MLINKS+=fgets.3 gets_s.3 MLINKS+=flockfile.3 ftrylockfile.3 flockfile.3 funlockfile.3 MLINKS+=fopen.3 fdopen.3 fopen.3 freopen.3 fopen.3 fmemopen.3 MLINKS+=fputs.3 puts.3 Index: lib/libc/stdio/Symbol.map =================================================================== --- lib/libc/stdio/Symbol.map +++ lib/libc/stdio/Symbol.map @@ -165,6 +165,7 @@ FBSD_1.4 { fdclose; fopencookie; + gets_s; }; FBSDprivate_1.0 { Index: lib/libc/stdio/fgets.3 =================================================================== --- lib/libc/stdio/fgets.3 +++ lib/libc/stdio/fgets.3 @@ -46,6 +46,8 @@ .Ft char * .Fn fgets "char * restrict str" "int size" "FILE * restrict stream" .Ft char * +.Fn gets_s "char *str" "rsize_t size" +.Ft char * .Fn gets "char *str" .Sh DESCRIPTION The @@ -65,6 +67,17 @@ character is appended to end the string. .Pp The +.Fn gets_s +function +is equivalent to +.Fn fgets +with a +.Fa stream +of +.Dv stdin , +except that the newline character (if any) is not stored in the string. +.Pp +The .Fn gets function is equivalent to @@ -80,7 +93,8 @@ if any, is sufficiently short to fit in the string. .Sh RETURN VALUES Upon successful completion, -.Fn fgets +.Fn fgets , +.Fn gets_s and .Fn gets return @@ -94,7 +108,8 @@ .Dv NULL and the buffer contents are indeterminate. The -.Fn fgets +.Fn fgets , +.Fn gets_s and .Fn gets functions @@ -141,6 +156,13 @@ .Fn gets conform to .St -isoC-99 . +.Fn gets_s +conforms to +.St -isoC-2011 +K.3.7.4.1. +.Fn gets +has been removed from +.St -isoC-2011 . .Sh SECURITY CONSIDERATIONS The .Fn gets Index: lib/libc/stdio/gets_s.c =================================================================== --- /dev/null +++ lib/libc/stdio/gets_s.c @@ -0,0 +1,101 @@ +/*- + * Copyright (c) 1990, 1993, 2017 + * The Regents of the University of California. All rights reserved. + * Cyril S. E. Schubert. All rights reserved. (2017) + * + * 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include "namespace.h" +#include +#include +#include +#include +#include "un-namespace.h" +#include "libc_private.h" +#include "local.h" + +/* ISO/IEC 9899:2011 K.3.7.4.1 */ +char * +gets_s(char *buf, rsize_t n) +{ + int c; + int throw_error = 0; + char *s, *ret; + + if (buf == NULL) { + __throw_constraint_handler_s("gets_s : str is NULL", EINVAL); + return(NULL); + } else if (n > RSIZE_MAX) { + __throw_constraint_handler_s("gets_s : n > RSIZE_MAX", + EINVAL); + return(NULL); + } else if (n == 0) { + __throw_constraint_handler_s("gets_s : n == 0", EINVAL); + return(NULL); + } + + FLOCKFILE_CANCELSAFE(stdin); + ORIENT(stdin, -1); + for (s = buf, n--; (c = __sgetc(stdin)) != '\n' && n > 0 ; n--) { + if (c == EOF) + if (s == buf) { + ret = NULL; + goto end; + } else + break; + else + *s++ = c; + } + + /* + * + * If end of buffer reached, discard until \n or eof. + * Then throw an error. + * + */ + if ( n == 0) { + /* discard */ + while (((c = __sgetc(stdin)) != '\n') && c != EOF); + /* throw the error after lock released prior to exit */ + throw_error = E2BIG; + ret = NULL; + goto end; + } + + *s = 0; + ret = buf; +end: + FUNLOCKFILE_CANCELSAFE(); + if (throw_error == E2BIG) + __throw_constraint_handler_s("gets_s : end of buffer", E2BIG); + return (ret); +}