From 9ceb2c49ae79c40e7836589cf3f04385043e45e6 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Mon, 22 Nov 2021 18:39:45 +0000 Subject: [PATCH] testcrypt: introduce and use 'checkenum' protocol query. This allows the Python side of testcrypt to check in advance if a given string is a valid element of an enumeration, and if not, cleanly throw a Python-level exception without terminating the testcrypt subprocess. Should be useful in both manual use (when I'm trying something out by hand and make a typo or misremember a spelling), and automated use (if I make the same kind of error in cryptsuite.py then the exception dump will make more sense). In order to do this, the new handle_checkenum() function has to recognise all the enumerated types by name and match them up to their lookup functions - which is just the kind of thing that can now be done easily be reincluding testcrypt-enum.h with different #defines. --- test/testcrypt.py | 10 +++++++++- testcrypt.c | 20 ++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/test/testcrypt.py b/test/testcrypt.py index d21f19c7..b71f851d 100644 --- a/test/testcrypt.py +++ b/test/testcrypt.py @@ -103,6 +103,8 @@ method_prefixes = { } method_lists = {t: [] for t in method_prefixes} +checked_enum_values = {} + class Value(object): def __init__(self, typename, ident): self._typename = typename @@ -182,7 +184,13 @@ def make_argword(arg, argtype, fnname, argindex, argname, to_preserve): "argon2flavour", "fptype", "httpdigesthash"}: arg = coerce_to_bytes(arg) if isinstance(arg, bytes) and b" " not in arg: - return arg + dictkey = (typename, arg) + if dictkey not in checked_enum_values: + retwords = childprocess.funcall("checkenum", [typename, arg]) + assert len(retwords) == 1 + checked_enum_values[dictkey] = (retwords[0] == b"ok") + if checked_enum_values[dictkey]: + return arg if typename == "mpint_list": sublist = [make_argword(len(arg), ("uint", False), fnname, argindex, argname, to_preserve)] diff --git a/testcrypt.c b/testcrypt.c index f6cb8517..68e2d11d 100644 --- a/testcrypt.c +++ b/testcrypt.c @@ -623,6 +623,25 @@ static void handle_mp_dump(BinarySource *in, strbuf *out) put_byte(out, '\n'); } +static void handle_checkenum(BinarySource *in, strbuf *out) +{ + ptrlen type = get_word(in); + ptrlen value = get_word(in); + bool ok = false; + + #define BEGIN_ENUM_TYPE(name) \ + if (ptrlen_eq_string(type, #name)) \ + ok = enum_translate_##name(value, NULL); + #define ENUM_VALUE(name, value) + #define END_ENUM_TYPE(name) + #include "testcrypt-enum.h" + #undef BEGIN_ENUM_TYPE + #undef ENUM_VALUE + #undef END_ENUM_TYPE + + put_dataz(out, ok ? "ok\n" : "bad\n"); +} + static void random_queue(ptrlen pl) { bufchain_add(&random_data_queue, pl.ptr, pl.len); @@ -1356,6 +1375,7 @@ static void process_line(BinarySource *in, strbuf *out) DISPATCH_COMMAND(getstring); DISPATCH_COMMAND(mp_literal); DISPATCH_COMMAND(mp_dump); + DISPATCH_COMMAND(checkenum); #undef DISPATCH_COMMAND #define FUNC_INNER(outtype, fname, realname, args) \