summaryrefslogtreecommitdiffstats
path: root/libc/include
diff options
context:
space:
mode:
authorNick Kralevich <nnk@google.com>2012-07-09 12:28:35 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2012-07-09 12:28:35 -0700
commita099e8e7d35a0e740477f9362e9360b42b98d9cd (patch)
treea6369ee8ff2c8218dd6e92eebf84637a863de661 /libc/include
parent793e6aedf2dfb6cc9bdf0cf9fd60dd87ec21f658 (diff)
parent965dbc6405aa2c3170270cfc53a8d4416444fddb (diff)
downloadbionic-a099e8e7d35a0e740477f9362e9360b42b98d9cd.zip
bionic-a099e8e7d35a0e740477f9362e9360b42b98d9cd.tar.gz
bionic-a099e8e7d35a0e740477f9362e9360b42b98d9cd.tar.bz2
Merge "FORTIFY_SOURCE: add fgets support."
Diffstat (limited to 'libc/include')
-rw-r--r--libc/include/stdio.h39
1 files changed, 39 insertions, 0 deletions
diff --git a/libc/include/stdio.h b/libc/include/stdio.h
index 18b19bf..c12ddb8 100644
--- a/libc/include/stdio.h
+++ b/libc/include/stdio.h
@@ -527,6 +527,45 @@ int sprintf(char *dest, const char *format, ...)
# endif /* !defined(__clang__) */
+extern char *__fgets_real(char *, int, FILE *)
+ __asm__(__USER_LABEL_PREFIX__ "fgets");
+extern void __fgets_too_big_error()
+ __attribute__((__error__("fgets called with size bigger than buffer")));
+extern void __fgets_too_small_error()
+ __attribute__((__error__("fgets called with size less than zero")));
+extern char *__fgets_chk(char *, int, FILE *, size_t);
+
+__BIONIC_FORTIFY_INLINE
+char *fgets(char *dest, int size, FILE *stream)
+{
+ size_t bos = __builtin_object_size(dest, 0);
+
+ // Compiler can prove, at compile time, that the passed in size
+ // is always negative. Force a compiler error.
+ if (__builtin_constant_p(size) && (size < 0)) {
+ __fgets_too_small_error();
+ }
+
+ // Compiler doesn't know destination size. Don't call __fgets_chk
+ if (bos == (size_t) -1) {
+ return __fgets_real(dest, size, 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(size) && (size <= bos)) {
+ return __fgets_real(dest, size, 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(size) && (size > bos)) {
+ __fgets_too_big_error();
+ }
+
+ return __fgets_chk(dest, size, stream, bos);
+}
+
#endif /* defined(__BIONIC_FORTIFY_INLINE) */
#endif /* _STDIO_H_ */