<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>