<div dir="ltr"><div>you probably want to update Makefile.am for make distcheck to pass (even as a submodule).<br><br></div>otherwise, looks good<br></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Tue, Apr 9, 2013 at 6:00 PM, Christophe Fergeau <span dir="ltr"><<a href="mailto:cfergeau@redhat.com" target="_blank">cfergeau@redhat.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">In addition to Laszlo's commit fixing rhbz#928973, we can add<br>
some compile-time assertion to lz_common.h to help catch similar<br>
bugs in the future.<br>
This uses gnulib's verify.h to make sure at compile-time that<br>
the various constant arrays used in lz_common.h are of the expected<br>
size.<br>
I've checked that before Laszlo's patch, the assert triggers, and<br>
that it's gone after it.<br>
---<br>
 common/lz_common.h |   5 ++<br>
 common/verify.h    | 245 +++++++++++++++++++++++++++++++++++++++++++++++++++++<br>
 2 files changed, 250 insertions(+)<br>
 create mode 100644 common/verify.h<br>
<br>
diff --git a/common/lz_common.h b/common/lz_common.h<br>
index b5ce212..0fee991 100644<br>
--- a/common/lz_common.h<br>
+++ b/common/lz_common.h<br>
@@ -24,6 +24,7 @@<br>
 #define _LZ_COMMON_H<br>
<br>
 #include <spice/macros.h><br>
+#include "verify.h"<br>
<br>
 SPICE_BEGIN_DECLS<br>
<br>
@@ -57,6 +58,10 @@ static const int IS_IMAGE_TYPE_RGB[] = {0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1};<br>
 static const int PLT_PIXELS_PER_BYTE[] = {0, 8, 8, 2, 2, 1};<br>
 static const int RGB_BYTES_PER_PIXEL[] = {0, 1, 1, 1, 1, 1, 2, 3, 4, 4, 4, 1};<br>
<br>
+verify(SPICE_N_ELEMENTS(IS_IMAGE_TYPE_PLT) == (LZ_IMAGE_TYPE_A8 + 1));<br>
+verify(SPICE_N_ELEMENTS(IS_IMAGE_TYPE_RGB) == (LZ_IMAGE_TYPE_A8 + 1));<br>
+verify(SPICE_N_ELEMENTS(PLT_PIXELS_PER_BYTE) == (LZ_IMAGE_TYPE_PLT8 + 1));<br>
+verify(SPICE_N_ELEMENTS(RGB_BYTES_PER_PIXEL) == (LZ_IMAGE_TYPE_A8 + 1));<br>
<br>
 #define LZ_MAGIC (*(uint32_t *)"LZ  ")<br>
 #define LZ_VERSION_MAJOR 1U<br>
diff --git a/common/verify.h b/common/verify.h<br>
new file mode 100644<br>
index 0000000..8445e3d<br>
--- /dev/null<br>
+++ b/common/verify.h<br>
@@ -0,0 +1,245 @@<br>
+/* Compile-time assert-like macros.<br>
+<br>
+   Copyright (C) 2005-2006, 2009-2013 Free Software Foundation, Inc.<br>
+<br>
+   This program is free software: you can redistribute it and/or modify<br>
+   it under the terms of the GNU Lesser General Public License as published by<br>
+   the Free Software Foundation; either version 2.1 of the License, or<br>
+   (at your option) any later version.<br>
+<br>
+   This program is distributed in the hope that it will be useful,<br>
+   but WITHOUT ANY WARRANTY; without even the implied warranty of<br>
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the<br>
+   GNU Lesser General Public License for more details.<br>
+<br>
+   You should have received a copy of the GNU Lesser General Public License<br>
+   along with this program.  If not, see <<a href="http://www.gnu.org/licenses/" target="_blank">http://www.gnu.org/licenses/</a>>.  */<br>
+<br>
+/* Written by Paul Eggert, Bruno Haible, and Jim Meyering.  */<br>
+<br>
+#ifndef _GL_VERIFY_H<br>
+# define _GL_VERIFY_H<br>
+<br>
+<br>
+/* Define _GL_HAVE__STATIC_ASSERT to 1 if _Static_assert works as per C11.<br>
+   This is supported by GCC 4.6.0 and later, in C mode, and its use<br>
+   here generates easier-to-read diagnostics when verify (R) fails.<br>
+<br>
+   Define _GL_HAVE_STATIC_ASSERT to 1 if static_assert works as per C++11.<br>
+   This will likely be supported by future GCC versions, in C++ mode.<br>
+<br>
+   Use this only with GCC.  If we were willing to slow 'configure'<br>
+   down we could also use it with other compilers, but since this<br>
+   affects only the quality of diagnostics, why bother?  */<br>
+# if (4 < __GNUC__ || (__GNUC__ == 4 && 6 <= __GNUC_MINOR__)) && !defined __cplusplus<br>
+#  define _GL_HAVE__STATIC_ASSERT 1<br>
+# endif<br>
+/* The condition (99 < __GNUC__) is temporary, until we know about the<br>
+   first G++ release that supports static_assert.  */<br>
+# if (99 < __GNUC__) && defined __cplusplus<br>
+#  define _GL_HAVE_STATIC_ASSERT 1<br>
+# endif<br>
+<br>
+/* Each of these macros verifies that its argument R is nonzero.  To<br>
+   be portable, R should be an integer constant expression.  Unlike<br>
+   assert (R), there is no run-time overhead.<br>
+<br>
+   If _Static_assert works, verify (R) uses it directly.  Similarly,<br>
+   _GL_VERIFY_TRUE works by packaging a _Static_assert inside a struct<br>
+   that is an operand of sizeof.<br>
+<br>
+   The code below uses several ideas for C++ compilers, and for C<br>
+   compilers that do not support _Static_assert:<br>
+<br>
+   * The first step is ((R) ? 1 : -1).  Given an expression R, of<br>
+     integral or boolean or floating-point type, this yields an<br>
+     expression of integral type, whose value is later verified to be<br>
+     constant and nonnegative.<br>
+<br>
+   * Next this expression W is wrapped in a type<br>
+     struct _gl_verify_type {<br>
+       unsigned int _gl_verify_error_if_negative: W;<br>
+     }.<br>
+     If W is negative, this yields a compile-time error.  No compiler can<br>
+     deal with a bit-field of negative size.<br>
+<br>
+     One might think that an array size check would have the same<br>
+     effect, that is, that the type struct { unsigned int dummy[W]; }<br>
+     would work as well.  However, inside a function, some compilers<br>
+     (such as C++ compilers and GNU C) allow local parameters and<br>
+     variables inside array size expressions.  With these compilers,<br>
+     an array size check would not properly diagnose this misuse of<br>
+     the verify macro:<br>
+<br>
+       void function (int n) { verify (n < 0); }<br>
+<br>
+   * For the verify macro, the struct _gl_verify_type will need to<br>
+     somehow be embedded into a declaration.  To be portable, this<br>
+     declaration must declare an object, a constant, a function, or a<br>
+     typedef name.  If the declared entity uses the type directly,<br>
+     such as in<br>
+<br>
+       struct dummy {...};<br>
+       typedef struct {...} dummy;<br>
+       extern struct {...} *dummy;<br>
+       extern void dummy (struct {...} *);<br>
+       extern struct {...} *dummy (void);<br>
+<br>
+     two uses of the verify macro would yield colliding declarations<br>
+     if the entity names are not disambiguated.  A workaround is to<br>
+     attach the current line number to the entity name:<br>
+<br>
+       #define _GL_CONCAT0(x, y) x##y<br>
+       #define _GL_CONCAT(x, y) _GL_CONCAT0 (x, y)<br>
+       extern struct {...} * _GL_CONCAT (dummy, __LINE__);<br>
+<br>
+     But this has the problem that two invocations of verify from<br>
+     within the same macro would collide, since the __LINE__ value<br>
+     would be the same for both invocations.  (The GCC __COUNTER__<br>
+     macro solves this problem, but is not portable.)<br>
+<br>
+     A solution is to use the sizeof operator.  It yields a number,<br>
+     getting rid of the identity of the type.  Declarations like<br>
+<br>
+       extern int dummy [sizeof (struct {...})];<br>
+       extern void dummy (int [sizeof (struct {...})]);<br>
+       extern int (*dummy (void)) [sizeof (struct {...})];<br>
+<br>
+     can be repeated.<br>
+<br>
+   * Should the implementation use a named struct or an unnamed struct?<br>
+     Which of the following alternatives can be used?<br>
+<br>
+       extern int dummy [sizeof (struct {...})];<br>
+       extern int dummy [sizeof (struct _gl_verify_type {...})];<br>
+       extern void dummy (int [sizeof (struct {...})]);<br>
+       extern void dummy (int [sizeof (struct _gl_verify_type {...})]);<br>
+       extern int (*dummy (void)) [sizeof (struct {...})];<br>
+       extern int (*dummy (void)) [sizeof (struct _gl_verify_type {...})];<br>
+<br>
+     In the second and sixth case, the struct type is exported to the<br>
+     outer scope; two such declarations therefore collide.  GCC warns<br>
+     about the first, third, and fourth cases.  So the only remaining<br>
+     possibility is the fifth case:<br>
+<br>
+       extern int (*dummy (void)) [sizeof (struct {...})];<br>
+<br>
+   * GCC warns about duplicate declarations of the dummy function if<br>
+     -Wredundant-decls is used.  GCC 4.3 and later have a builtin<br>
+     __COUNTER__ macro that can let us generate unique identifiers for<br>
+     each dummy function, to suppress this warning.<br>
+<br>
+   * This implementation exploits the fact that older versions of GCC,<br>
+     which do not support _Static_assert, also do not warn about the<br>
+     last declaration mentioned above.<br>
+<br>
+   * GCC warns if -Wnested-externs is enabled and verify() is used<br>
+     within a function body; but inside a function, you can always<br>
+     arrange to use verify_expr() instead.<br>
+<br>
+   * In C++, any struct definition inside sizeof is invalid.<br>
+     Use a template type to work around the problem.  */<br>
+<br>
+/* Concatenate two preprocessor tokens.  */<br>
+# define _GL_CONCAT(x, y) _GL_CONCAT0 (x, y)<br>
+# define _GL_CONCAT0(x, y) x##y<br>
+<br>
+/* _GL_COUNTER is an integer, preferably one that changes each time we<br>
+   use it.  Use __COUNTER__ if it works, falling back on __LINE__<br>
+   otherwise.  __LINE__ isn't perfect, but it's better than a<br>
+   constant.  */<br>
+# if defined __COUNTER__ && __COUNTER__ != __COUNTER__<br>
+#  define _GL_COUNTER __COUNTER__<br>
+# else<br>
+#  define _GL_COUNTER __LINE__<br>
+# endif<br>
+<br>
+/* Generate a symbol with the given prefix, making it unique if<br>
+   possible.  */<br>
+# define _GL_GENSYM(prefix) _GL_CONCAT (prefix, _GL_COUNTER)<br>
+<br>
+/* Verify requirement R at compile-time, as an integer constant expression<br>
+   that returns 1.  If R is false, fail at compile-time, preferably<br>
+   with a diagnostic that includes the string-literal DIAGNOSTIC.  */<br>
+<br>
+# define _GL_VERIFY_TRUE(R, DIAGNOSTIC) \<br>
+    (!!sizeof (_GL_VERIFY_TYPE (R, DIAGNOSTIC)))<br>
+<br>
+# ifdef __cplusplus<br>
+#  if !GNULIB_defined_struct__gl_verify_type<br>
+template <int w><br>
+  struct _gl_verify_type {<br>
+    unsigned int _gl_verify_error_if_negative: w;<br>
+  };<br>
+#   define GNULIB_defined_struct__gl_verify_type 1<br>
+#  endif<br>
+#  define _GL_VERIFY_TYPE(R, DIAGNOSTIC) \<br>
+    _gl_verify_type<(R) ? 1 : -1><br>
+# elif defined _GL_HAVE__STATIC_ASSERT<br>
+#  define _GL_VERIFY_TYPE(R, DIAGNOSTIC) \<br>
+     struct {                                   \<br>
+       _Static_assert (R, DIAGNOSTIC);          \<br>
+       int _gl_dummy;                          \<br>
+     }<br>
+# else<br>
+#  define _GL_VERIFY_TYPE(R, DIAGNOSTIC) \<br>
+     struct { unsigned int _gl_verify_error_if_negative: (R) ? 1 : -1; }<br>
+# endif<br>
+<br>
+/* Verify requirement R at compile-time, as a declaration without a<br>
+   trailing ';'.  If R is false, fail at compile-time, preferably<br>
+   with a diagnostic that includes the string-literal DIAGNOSTIC.<br>
+<br>
+   Unfortunately, unlike C11, this implementation must appear as an<br>
+   ordinary declaration, and cannot appear inside struct { ... }.  */<br>
+<br>
+# ifdef _GL_HAVE__STATIC_ASSERT<br>
+#  define _GL_VERIFY _Static_assert<br>
+# else<br>
+#  define _GL_VERIFY(R, DIAGNOSTIC)                                   \<br>
+     extern int (*_GL_GENSYM (_gl_verify_function) (void))            \<br>
+       [_GL_VERIFY_TRUE (R, DIAGNOSTIC)]<br>
+# endif<br>
+<br>
+/* _GL_STATIC_ASSERT_H is defined if this code is copied into assert.h.  */<br>
+# ifdef _GL_STATIC_ASSERT_H<br>
+#  if !defined _GL_HAVE__STATIC_ASSERT && !defined _Static_assert<br>
+#   define _Static_assert(R, DIAGNOSTIC) _GL_VERIFY (R, DIAGNOSTIC)<br>
+#  endif<br>
+#  if !defined _GL_HAVE_STATIC_ASSERT && !defined static_assert<br>
+#   define static_assert _Static_assert /* C11 requires this #define.  */<br>
+#  endif<br>
+# endif<br>
+<br>
+/* @assert.h omit start@  */<br>
+<br>
+/* Each of these macros verifies that its argument R is nonzero.  To<br>
+   be portable, R should be an integer constant expression.  Unlike<br>
+   assert (R), there is no run-time overhead.<br>
+<br>
+   There are two macros, since no single macro can be used in all<br>
+   contexts in C.  verify_true (R) is for scalar contexts, including<br>
+   integer constant expression contexts.  verify (R) is for declaration<br>
+   contexts, e.g., the top level.  */<br>
+<br>
+/* Verify requirement R at compile-time, as an integer constant expression.<br>
+   Return 1.  This is equivalent to verify_expr (R, 1).<br>
+<br>
+   verify_true is obsolescent; please use verify_expr instead.  */<br>
+<br>
+# define verify_true(R) _GL_VERIFY_TRUE (R, "verify_true (" #R ")")<br>
+<br>
+/* Verify requirement R at compile-time.  Return the value of the<br>
+   expression E.  */<br>
+<br>
+# define verify_expr(R, E) \<br>
+    (_GL_VERIFY_TRUE (R, "verify_expr (" #R ", " #E ")") ? (E) : (E))<br>
+<br>
+/* Verify requirement R at compile-time, as a declaration without a<br>
+   trailing ';'.  */<br>
+<br>
+# define verify(R) _GL_VERIFY (R, "verify (" #R ")")<br>
+<br>
+/* @assert.h omit end@  */<br>
+<br>
+#endif<br>
<span class="HOEnZb"><font color="#888888">--<br>
1.8.1.4<br>
<br>
_______________________________________________<br>
Spice-devel mailing list<br>
<a href="mailto:Spice-devel@lists.freedesktop.org">Spice-devel@lists.freedesktop.org</a><br>
<a href="http://lists.freedesktop.org/mailman/listinfo/spice-devel" target="_blank">http://lists.freedesktop.org/mailman/listinfo/spice-devel</a><br>
</font></span></blockquote></div><br><br clear="all"><br>-- <br>Marc-André Lureau
</div>