From 5ff263e65f0dade0458d23fb78dfea12c94eb2be Mon Sep 17 00:00:00 2001 From: Martin Date: Thu, 27 Aug 2015 21:51:30 +0200 Subject: [PATCH] Visual Studio 2015: exploit C99-conformant (v)snprintf in core.stdc.stdio --- src/core/stdc/stdio.d | 36 +++++++++++++++---------------- src/rt/stdio_msvc.c | 49 +++++++++++++++++++------------------------ 2 files changed, 39 insertions(+), 46 deletions(-) diff --git a/src/core/stdc/stdio.d b/src/core/stdc/stdio.d index ae2966a8a5..acdc57f83e 100644 --- a/src/core/stdc/stdio.d +++ b/src/core/stdc/stdio.d @@ -71,7 +71,7 @@ else version( CRuntime_Microsoft ) FOPEN_MAX = 20, /// FILENAME_MAX = 260, - /// + /// Actually int.max since Visual Studio 2015. TMP_MAX = 32767, /// _SYS_OPEN = 20, // non-standard @@ -79,11 +79,11 @@ else version( CRuntime_Microsoft ) /// enum int _NFILE = 512; // non-standard - /// + /// Removed since Visual Studio 2015. enum string _P_tmpdir = "\\"; // non-standard - /// + /// Removed since Visual Studio 2015. enum wstring _wP_tmpdir = "\\"; // non-standard - /// + /// Actually 260 since Visual Studio 2015. enum int L_tmpnam = _P_tmpdir.length + 12; } else version( CRuntime_Glibc ) @@ -543,23 +543,23 @@ else version( CRuntime_Microsoft ) _IOLBF = 0x40, /// _IONBF = 4, - /// + /// Removed since Visual Studio 2015. _IOREAD = 1, // non-standard - /// + /// Removed since Visual Studio 2015. _IOWRT = 2, // non-standard - /// + /// Removed since Visual Studio 2015. _IOMYBUF = 8, // non-standard - /// + /// Removed since Visual Studio 2015. _IOEOF = 0x10, // non-standard - /// + /// Removed since Visual Studio 2015. _IOERR = 0x20, // non-standard - /// + /// Removed since Visual Studio 2015. _IOSTRG = 0x40, // non-standard - /// + /// Removed since Visual Studio 2015. _IORW = 0x80, // non-standard - /// + /// Removed since Visual Studio 2015. _IOAPP = 0x200, // non-standard - /// + /// Removed since Visual Studio 2015. _IOAPPEND = 0x200, // non-standard } @@ -941,19 +941,19 @@ else version( CRuntime_Microsoft ) /// pure int fileno(FILE* stream); } + /// - int _snprintf(char* s, size_t n, in char* fmt, ...); + int _snprintf(char* s, size_t n, in char* format, ...); /// - alias _snprintf snprintf; + int snprintf(char* s, size_t n, in char* format, ...); /// - int _vsnprintf(char* s, size_t n, in char* format, va_list arg); + int _vsnprintf(char* s, size_t n, in char* format, va_list arg); /// - alias _vsnprintf vsnprintf; + int vsnprintf(char* s, size_t n, in char* format, va_list arg); /// int _fputc_nolock(int c, FILE *fp); - /// int _fgetc_nolock(FILE *fp); diff --git a/src/rt/stdio_msvc.c b/src/rt/stdio_msvc.c index 92f0f9b7c6..a81042643f 100644 --- a/src/rt/stdio_msvc.c +++ b/src/rt/stdio_msvc.c @@ -53,12 +53,21 @@ void init_msvc() FILE* fp = __iob_func(); stdin = fp; stdout = fp + 1; - stderr = fp + 1; + stderr = fp + 2; } if (&_set_output_format != (void*) &_nullfunc) - _set_output_format(1); + { + const int _TWO_DIGIT_EXPONENT = 1; + _set_output_format(_TWO_DIGIT_EXPONENT); + } } +// VS2015+ provides C99-conformant (v)snprintf functions, so weakly +// link to legacy _(v)snprintf (not C99-conformant!) for VS2013- only + +#pragma comment(linker, "/alternatename:snprintf=_snprintf") +#pragma comment(linker, "/alternatename:vsnprintf=_vsnprintf") + // VS2013- implements these functions as macros, VS2015+ provides symbols #pragma comment(linker, "/alternatename:_fputc_nolock=_msvc_fputc_nolock") @@ -70,13 +79,13 @@ void init_msvc() #pragma comment(linker, "/alternatename:fileno=_msvc_fileno") // VS2013- helper functions -int _filbuf(FILE *fp); -int _flsbuf(int c, FILE *fp); +int _filbuf(FILE* fp); +int _flsbuf(int c, FILE* fp); #pragma comment(linker, "/alternatename:_filbuf=_nullfunc") #pragma comment(linker, "/alternatename:_flsbuf=_nullfunc") -int _msvc_fputc_nolock(int c, FILE *fp) +int _msvc_fputc_nolock(int c, FILE* fp) { fp->_cnt = fp->_cnt - 1; if (fp->_cnt >= 0) @@ -89,7 +98,7 @@ int _msvc_fputc_nolock(int c, FILE *fp) return _flsbuf(c, fp); } -int _msvc_fgetc_nolock(FILE *fp) +int _msvc_fgetc_nolock(FILE* fp) { fp->_cnt = fp->_cnt - 1; if (fp->_cnt >= 0) @@ -104,38 +113,22 @@ int _msvc_fgetc_nolock(FILE *fp) enum { - _IOFBF = 0, - _IOLBF = 0x40, - _IONBF = 4, - _IOREAD = 1, // non-standard - _IOWRT = 2, // non-standard - _IOMYBUF = 8, // non-standard - _IOEOF = 0x10, // non-standard - _IOERR = 0x20, // non-standard - _IOSTRG = 0x40, // non-standard - _IORW = 0x80, // non-standard - _IOAPP = 0x200, // non-standard - _IOAPPEND = 0x200, // non-standard + SEEK_SET = 0, + _IOEOF = 0x10, + _IOERR = 0x20 }; -enum -{ - SEEK_SET, - SEEK_CUR, - SEEK_END -}; - -int fseek(FILE *fp, long off, int whence); +int fseek(FILE* fp, long off, int whence); void _msvc_rewind(FILE* stream) { fseek(stream, 0L, SEEK_SET); stream->_flag = stream->_flag & ~_IOERR; } -/// + void _msvc_clearerr(FILE* stream) { - stream->_flag = stream->_flag & ~(_IOERR|_IOEOF); + stream->_flag = stream->_flag & ~(_IOERR | _IOEOF); } int _msvc_feof(FILE* stream)