[PATCH] static buffer overflow checking
Marcus Meissner
meissner at suse.de
Thu Sep 11 15:12:43 CDT 2008
Hi,
This checks for a case, where buffers passed to MultiByteToWideChar
and WideChartoMultiByte do not match the size passed.
Usually a WCHAR buf[xx] is passed and sizeof(buf) as size.
The check is done at compile time only, and the wrap code will be
optimized away completely.
resubmit:
Disabled on -O0 and for GCC < 4
Added #undef in kernel32/locale.c (where the function is defined)
Added #undef in tests/codepage.c (where there are actual (wanted?)
buffer overflows)
(A successful testrun will need my previous shell32 patch from today.)
Ciao, Marcus
---
dlls/kernel32/locale.c | 2 +
dlls/kernel32/tests/codepage.c | 3 ++
include/winnls.h | 41 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 46 insertions(+), 0 deletions(-)
diff --git a/dlls/kernel32/locale.c b/dlls/kernel32/locale.c
index 8aedacb..c72d05e 100644
--- a/dlls/kernel32/locale.c
+++ b/dlls/kernel32/locale.c
@@ -1796,6 +1796,7 @@ BOOL WINAPI EnumSystemCodePagesW( CODEPAGE_ENUMPROCW lpfnCodePageEnum, DWORD fla
* is passed, and ERROR_NO_UNICODE_TRANSLATION if no translation is
* possible for src.
*/
+#undef MultiByteToWideChar
INT WINAPI MultiByteToWideChar( UINT page, DWORD flags, LPCSTR src, INT srclen,
LPWSTR dst, INT dstlen )
{
@@ -1887,6 +1888,7 @@ INT WINAPI MultiByteToWideChar( UINT page, DWORD flags, LPCSTR src, INT srclen,
* and dstlen != 0, and ERROR_INVALID_PARAMETER, if an invalid
* parameter was given.
*/
+#undef WideCharToMultiByte
INT WINAPI WideCharToMultiByte( UINT page, DWORD flags, LPCWSTR src, INT srclen,
LPSTR dst, INT dstlen, LPCSTR defchar, BOOL *used )
{
diff --git a/dlls/kernel32/tests/codepage.c b/dlls/kernel32/tests/codepage.c
index c7daf19..2f74446 100644
--- a/dlls/kernel32/tests/codepage.c
+++ b/dlls/kernel32/tests/codepage.c
@@ -29,6 +29,9 @@
static const WCHAR foobarW[] = {'f','o','o','b','a','r',0};
+#undef MultiByteToWideChar
+#undef WideCharToMultiByte
+
static void test_destination_buffer(void)
{
LPSTR buffer;
diff --git a/include/winnls.h b/include/winnls.h
index 50d6389..a5f5e56 100644
--- a/include/winnls.h
+++ b/include/winnls.h
@@ -788,6 +788,47 @@ WINBASEAPI BOOL WINAPI SetThreadLocale(LCID);
WINBASEAPI BOOL WINAPI SetUserGeoID(GEOID);
WINBASEAPI INT WINAPI WideCharToMultiByte(UINT,DWORD,LPCWSTR,INT,LPSTR,INT,LPCSTR,LPBOOL);
+#if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__OPTIMIZE__)
+extern void MBtoWC_incorrect_source_buffer_size(void);
+extern void MBtoWC_incorrect_destination_buffer_size__divide_by_sizeof_WCHAR(void);
+static inline INT
+WINAPI MultiByteToWideChar_ichk(
+ UINT cp,DWORD flags,
+ LPCSTR src,INT srclen,
+ LPWSTR dst,INT dstlen
+) {
+ int dstbuflen = __builtin_object_size(dst,0);
+ int srcbuflen = __builtin_object_size(src,0);
+
+ if (__builtin_constant_p(srclen) && (srclen != -1) && (srcbuflen != -1) && (srcbuflen < srclen))
+ MBtoWC_incorrect_source_buffer_size();
+ if (__builtin_constant_p(dstlen) && (dstlen != -1) && (dstbuflen != -1) && (dstbuflen/2 < dstlen))
+ MBtoWC_incorrect_destination_buffer_size__divide_by_sizeof_WCHAR();
+ return MultiByteToWideChar(cp,flags,src,srclen,dst,dstlen);
+}
+#define MultiByteToWideChar MultiByteToWideChar_ichk
+
+extern void WCtoMB_incorrect_source_buffer_size__divide_by_sizeof_WCHAR(void);
+extern void WCtoMB_incorrect_dest_buffer_size(void);
+static inline INT
+WINAPI WideCharToMultiByte_ichk(
+ UINT cp,DWORD flags,
+ LPCWSTR src,INT srclen,
+ LPSTR dst,INT dstlen,
+ LPCSTR xstr,LPBOOL b
+) {
+ int dstbuflen = __builtin_object_size(dst,0);
+ int srcbuflen = __builtin_object_size(src,0);
+
+ if (__builtin_constant_p(srclen) && (srclen != -1) && (srcbuflen != -1) && (srcbuflen/2 < srclen))
+ WCtoMB_incorrect_source_buffer_size__divide_by_sizeof_WCHAR();
+ if (__builtin_constant_p(dstlen) && (dstlen != -1) && (dstbuflen != -1) && (dstbuflen < dstlen))
+ WCtoMB_incorrect_dest_buffer_size();
+ return WideCharToMultiByte(cp,flags,src,srclen,dst,dstlen,xstr,b);
+}
+#define WideCharToMultiByte WideCharToMultiByte_ichk
+
+#endif /* gnuc >= 4 optimizing */
#ifdef __cplusplus
}
#endif
--
1.5.6
More information about the wine-patches
mailing list