catacomb.c, util.c: Publish `KERR_...' symbols as negative numbers.
authorMark Wooding <mdw@distorted.org.uk>
Sun, 24 Nov 2019 15:11:46 +0000 (15:11 +0000)
committerMark Wooding <mdw@distorted.org.uk>
Mon, 25 Nov 2019 17:31:22 +0000 (17:31 +0000)
They're supposed to be, but the existing `setconstants' machinery isn't
clever enough to do this properly.

Fixing this involves adding a flags word to `struct nameval' to identify
which constants should really be signed, and some fancy footwork to
convert unsigned integers back to negative values without upsetting C.

catacomb-python.h
catacomb.c
util.c

index c272b53..b1120fa 100644 (file)
@@ -233,7 +233,8 @@ MODULES(DO)
     return (d);                                                                \
   }
 
-struct nameval { const char *name; unsigned long value; };
+struct nameval { const char *name; unsigned f; unsigned long value; };
+#define CF_SIGNED 1u
 extern void setconstants(PyObject *, const struct nameval *);
 
 extern PyObject *mexp_common(PyObject *, PyObject *, size_t,
index d7b3dc7..edb0c4a 100644 (file)
@@ -31,7 +31,8 @@
 /*----- Main code ---------------------------------------------------------*/
 
 static const struct nameval consts[] = {
-#define C(x) { #x, x }
+#define CF(f, x) { #x, f, x }
+#define C(x) { #x, 0, x }
   C(FTY_PRIME), C(FTY_BINARY),
   C(PGEN_PASS), C(PGEN_FAIL), C(PGEN_BEGIN), C(PGEN_TRY), C(PGEN_DONE),
   C(PGEN_ABORT),
@@ -51,10 +52,11 @@ static const struct nameval consts[] = {
   C(ED25519_KEYSZ), C(ED25519_PUBSZ), C(ED25519_SIGSZ),
     C(ED25519_MAXPERSOSZ),
   C(ED448_KEYSZ), C(ED448_PUBSZ), C(ED448_SIGSZ), C(ED448_MAXPERSOSZ),
-#define ENTRY(tag, val, str) C(KERR_##tag),
+#define ENTRY(tag, val, str) CF(CF_SIGNED, KERR_##tag),
   KEY_ERRORS(ENTRY)
 #undef ENTRY
 #undef C
+#undef CF
   { 0 }
 };
 
diff --git a/util.c b/util.c
index d613a7a..9332c8b 100644 (file)
--- a/util.c
+++ b/util.c
@@ -280,14 +280,14 @@ PyTypeObject *inittype(PyTypeObject *tyskel, PyTypeObject *meta)
 void setconstants(PyObject *mod, const struct nameval *c)
 {
   PyObject *x;
+  unsigned long u;
 
   while (c->name) {
-    if (c->value > LONG_MAX)
-      x = PyLong_FromUnsignedLong(c->value);
-    else
-      x = PyInt_FromLong(c->value);
-    PyModule_AddObject(mod, (/*unconst*/ char *)c->name, x);
-    c++;
+    u = c->value;
+    if (u <= LONG_MAX) x = PyInt_FromLong(u);
+    else if (c->f&CF_SIGNED) x = PyInt_FromLong(-1 - (long)(ULONG_MAX - u));
+    else x = PyLong_FromUnsignedLong(u);
+    PyModule_AddObject(mod, (/*unconst*/ char *)c->name, x); c++;
   }
 }