RFC: Adding annotations to function declarations to improve static analysis

Marcus Meissner marcus at jet.franken.de
Sat Sep 27 23:38:34 CDT 2008


On Sun, Sep 28, 2008 at 12:08:22AM +0100, Rob Shearman wrote:
> Hi all,
> 
> This will be talked about in more detail at WineConf tomorrow, but I
> just thought I'd throw this out there as a bit of background to any
> discussions.
> 
> Adding annotations to function declarations allows Prefast to pick up
> certain classes of bugs with varying degrees of false positives. In
> particular, with patches like the attached applied
> byte-count/element-count mismatches can be detected with no false
> positives and relatively few false positives for off-by-one errors and
> other buffer overruns. Whilst this could be maintained outside of the
> main Wine tree it would be more convenient in terms of automation of
> Prefast runs if a vanilla Wine tree can be used (i.e. the annotation
> patches are in the official tree).

I have done something similar using small inline wrapper functions,
which works reliable for fixed size compiletime passed buffers and
sizes.

These wrappers will emit undefined functions when wrong and so fail
the build. Note the if() will be optimized away completely.

Redefining functions will however not work when programs use the function
names in other contexts, as struct names or similar.

Sample for 2 winver.h functions:


diff --git a/dlls/kernel32/locale.c b/dlls/kernel32/locale.c
index c72d05e..a8de2a2 100644
--- a/dlls/kernel32/locale.c
+++ b/dlls/kernel32/locale.c
@@ -2166,6 +2169,7 @@ BOOL WINAPI EnumSystemLocalesW( LOCALE_ENUMPROCW lpfnLocaleEnum, DWORD dwFlags )
  *  Failure: 0. Use GetLastError() to determine the cause.
  *
  */
+#undef VerLanguageNameA
 DWORD WINAPI VerLanguageNameA( DWORD wLang, LPSTR szLang, DWORD nSize )
 {
     return GetLocaleInfoA( MAKELCID(wLang, SORT_DEFAULT), LOCALE_SENGLANGUAGE, szLang, nSize );
@@ -2177,6 +2181,7 @@ DWORD WINAPI VerLanguageNameA( DWORD wLang, LPSTR szLang, DWORD nSize )
  *
  * See VerLanguageNameA.
  */
+#undef VerLanguageNameW
 DWORD WINAPI VerLanguageNameW( DWORD wLang, LPWSTR szLang, DWORD nSize )
 {
     return GetLocaleInfoW( MAKELCID(wLang, SORT_DEFAULT), LOCALE_SENGLANGUAGE, szLang, nSize );
diff --git a/include/winver.h b/include/winver.h
index f7e887b..cb06852 100644
--- a/include/winver.h
+++ b/include/winver.h
@@ -170,6 +170,23 @@ BOOL        WINAPI GetFileVersionInfoW(LPCWSTR,DWORD,DWORD,LPVOID);
 #define     GetFileVersionInfo WINELIB_NAME_AW(GetFileVersionInfo)
 
 /* 20 GETFILEVERSIONINFORAW */
+#if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__OPTIMIZE__)
+#define make_checker(func,type,arglist1,arglist2,namebuf,namebuflen,charsize)	\
+extern void func##_sizeincorrect(void);						\
+static inline type func##_ichk arglist1  {					\
+	int namebuf##len = __builtin_object_size(namebuf, 0);			\
+										\
+	if (__builtin_constant_p(namebuflen) && (namebuf##len != -1) && (namebuflen*charsize > namebuf##len)) \
+		func##_sizeincorrect();						\
+	return func arglist2 ;							\
+}										
+make_checker(VerLanguageNameA,DWORD WINAPI,(DWORD a,LPSTR b,DWORD c),(a,b,c),b,c,1)
+#define VerLanguageNameA VerLanguageNameA_ichk
+make_checker(VerLanguageNameW,DWORD WINAPI,(DWORD a,LPWSTR b,DWORD c),(a,b,c),b,c,2)
+#define VerLanguageNameW VerLanguageNameW_ichk
+
+#endif /* overflow checker */
+
 
 #endif /* RC_INVOKED */
 
-- 
1.5.6




More information about the wine-devel mailing list