[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