Commits

Armin Rigo committed c3942c4

Issue #118: improve the detection and error message, jumping
through hoops to cover both signed and unsigned cases.

Comments (0)

Files changed (3)

cffi/vengine_cpy.py

         prnt('static int %s(PyObject *lib)' % funcname)
         prnt('{')
         for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues):
-            prnt('  if (%s != %d) {' % (enumerator, enumvalue))
+            if enumvalue < 0:
+                prnt('  if ((%s) >= 0 || (long)(%s) != %dL) {' % (
+                    enumerator, enumerator, enumvalue))
+            else:
+                prnt('  if ((%s) < 0 || (unsigned long)(%s) != %dUL) {' % (
+                    enumerator, enumerator, enumvalue))
+            prnt('    char buf[64];')
+            prnt('    if ((%s) < 0)' % enumerator)
+            prnt('        snprintf(buf, 63, "%%ld", (long)(%s));' % enumerator)
+            prnt('    else')
+            prnt('        snprintf(buf, 63, "%%lu", (unsigned long)(%s));' %
+                 enumerator)
             prnt('    PyErr_Format(_cffi_VerificationError,')
-            prnt('                 "enum %s: %s has the real value %d, '
-                 'not %d",')
-            prnt('                 "%s", "%s", (int)%s, %d);' % (
-                name, enumerator, enumerator, enumvalue))
+            prnt('                 "enum %s: %s has the real value %s, '
+                 'not %s",')
+            prnt('                 "%s", "%s", buf, "%d");' % (
+                name, enumerator, enumvalue))
             prnt('    return -1;')
             prnt('  }')
         prnt('  return %s;' % self._chained_list_constants[True])

cffi/vengine_gen.py

         prnt('int %s(char *out_error)' % funcname)
         prnt('{')
         for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues):
-            prnt('  if (%s != %d) {' % (enumerator, enumvalue))
+            if enumvalue < 0:
+                prnt('  if ((%s) >= 0 || (long)(%s) != %dL) {' % (
+                    enumerator, enumerator, enumvalue))
+            else:
+                prnt('  if ((%s) < 0 || (unsigned long)(%s) != %dUL) {' % (
+                    enumerator, enumerator, enumvalue))
+            prnt('    char buf[64];')
+            prnt('    if ((%s) < 0)' % enumerator)
+            prnt('        snprintf(buf, 63, "%%ld", (long)(%s));' % enumerator)
+            prnt('    else')
+            prnt('        snprintf(buf, 63, "%%lu", (unsigned long)(%s));' %
+                 enumerator)
             prnt('    snprintf(out_error, 255,'
-                             '"%s has the real value %d, not %d",')
-            prnt('            "%s", (int)%s, %d);' % (
-                enumerator, enumerator, enumvalue))
+                             ' "%s has the real value %s, not %s",')
+            prnt('            "%s", buf, "%d");' % (
+                enumerator, enumvalue))
             prnt('    return -1;')
             prnt('  }')
         prnt('  return 0;')

testing/test_verify.py

 ##        assert ffi.sizeof("enum foo_e") == expected_size
 ##        assert int(ffi.cast("enum foo_e", -1)) == expected_minus1
 
+def test_enum_bug118():
+    maxulong = 256 ** FFI().sizeof("unsigned long") - 1
+    for c1, c2, c2c in [(0xffffffff, -1, ''),
+                        (maxulong, -1, ''),
+                        (-1, 0xffffffff, 'U'),
+                        (-1, maxulong, 'UL')]:
+        ffi = FFI()
+        ffi.cdef("enum foo_e { AA=%s };" % c1)
+        e = py.test.raises(VerificationError, ffi.verify,
+                           "enum foo_e { AA=%s%s };" % (c2, c2c))
+        assert str(e.value) == ('enum foo_e: AA has the real value %d, not %d'
+                                % (c2, c1))
+
 def test_string_to_voidp_arg():
     ffi = FFI()
     ffi.cdef("int myfunc(void *);")
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.