From daeeca55a4ef109539dc3e67b758299cc03d35ea Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Wed, 16 Dec 2015 14:40:00 +0000 Subject: [PATCH] Promote 'testbn' to a binary built by the makefiles. This makes it easier to compile in multiple debugging modes, or on Windows, without having to constantly paste annoying test-compile commands out of comments in sshbn.c. The new binary is compiled into the build directory, but not shipped by 'make install', just like fuzzterm. Unlike fuzzterm, though, testbn is also compiled on Windows, for which we didn't already have a mechanism for building unshipped binaries; I've done the very simplest thing for the moment, of providing a target in Makefile.vc to delete them. In order to comply with the PuTTY makefile system's constraint of never compiling the same object multiple times with different ifdefs, I've also moved testbn's main() out into its own source file. --- Buildscr | 2 +- Recipe | 11 +++ sshbn.c | 266 ------------------------------------------------------- testbn.c | 265 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 277 insertions(+), 267 deletions(-) create mode 100644 testbn.c diff --git a/Buildscr b/Buildscr index c9420658..84dda5c7 100644 --- a/Buildscr +++ b/Buildscr @@ -150,7 +150,7 @@ in putty do perl -i~ -pe 'y/\015//d;s/$$/\015/' LICENCE delegate windows # FIXME: Cygwin alternative? - in putty/windows do/win vcvars32 && nmake -f Makefile.vc $(Makeargs) + in putty/windows do/win vcvars32 && nmake -f Makefile.vc $(Makeargs) all cleantestprogs # Code-sign the binaries, if the local bob config provides a script # to do so. We assume here that the script accepts an -i option to # provide a 'more info' URL, and an optional -n option to provide a diff --git a/Recipe b/Recipe index fc8e444a..0d119d13 100644 --- a/Recipe +++ b/Recipe @@ -323,3 +323,14 @@ PuTTY : [MX] osxmain OSXTERM OSXMISC CHARSET U_BE_ALL NONSSH UXSSH fuzzterm : [UT] UXTERM CHARSET misc uxmisc uxucs fuzzterm time settings + uxstore be_none +testbn : [UT] testbn sshbn misc conf tree234 uxmisc +testbn : [C] testbn sshbn misc conf tree234 winmisc LIBS + +# ---------------------------------------------------------------------- +# On Windows, provide a means of removing local test binaries that we +# aren't going to actually ship. (I prefer this to not building them +# in the first place, so that we find out about build breakage early.) +!begin vc +cleantestprogs: + -del testbn.exe +!end diff --git a/sshbn.c b/sshbn.c index 4f27dc9b..724cf301 100644 --- a/sshbn.c +++ b/sshbn.c @@ -2180,269 +2180,3 @@ char *bignum_decimal(Bignum x) sfree(workspace); return ret; } - -#ifdef TESTBN - -#include -#include -#include - -/* - * gcc -Wall -g -O0 -DTESTBN -o testbn sshbn.c misc.c conf.c tree234.c unix/uxmisc.c -I. -I unix -I charset - * - * Then feed to this program's standard input the output of - * testdata/bignum.py . - */ - -void modalfatalbox(const char *p, ...) -{ - va_list ap; - fprintf(stderr, "FATAL ERROR: "); - va_start(ap, p); - vfprintf(stderr, p, ap); - va_end(ap); - fputc('\n', stderr); - exit(1); -} - -int random_byte(void) -{ - modalfatalbox("random_byte called in testbn"); - return 0; -} - -#define fromxdigit(c) ( (c)>'9' ? ((c)&0xDF) - 'A' + 10 : (c) - '0' ) - -int main(int argc, char **argv) -{ - char *buf; - int line = 0; - int passes = 0, fails = 0; - - while ((buf = fgetline(stdin)) != NULL) { - int maxlen = strlen(buf); - unsigned char *data = snewn(maxlen, unsigned char); - unsigned char *ptrs[5], *q; - int ptrnum; - char *bufp = buf; - - line++; - - q = data; - ptrnum = 0; - - while (*bufp && !isspace((unsigned char)*bufp)) - bufp++; - if (bufp) - *bufp++ = '\0'; - - while (*bufp) { - char *start, *end; - int i; - - while (*bufp && !isxdigit((unsigned char)*bufp)) - bufp++; - start = bufp; - - if (!*bufp) - break; - - while (*bufp && isxdigit((unsigned char)*bufp)) - bufp++; - end = bufp; - - if (ptrnum >= lenof(ptrs)) - break; - ptrs[ptrnum++] = q; - - for (i = -((end - start) & 1); i < end-start; i += 2) { - unsigned char val = (i < 0 ? 0 : fromxdigit(start[i])); - val = val * 16 + fromxdigit(start[i+1]); - *q++ = val; - } - - ptrs[ptrnum] = q; - } - - if (!strcmp(buf, "mul")) { - Bignum a, b, c, p; - - if (ptrnum != 3) { - printf("%d: mul with %d parameters, expected 3\n", line, ptrnum); - exit(1); - } - a = bignum_from_bytes(ptrs[0], ptrs[1]-ptrs[0]); - b = bignum_from_bytes(ptrs[1], ptrs[2]-ptrs[1]); - c = bignum_from_bytes(ptrs[2], ptrs[3]-ptrs[2]); - p = bigmul(a, b); - - if (bignum_cmp(c, p) == 0) { - passes++; - } else { - char *as = bignum_decimal(a); - char *bs = bignum_decimal(b); - char *cs = bignum_decimal(c); - char *ps = bignum_decimal(p); - - printf("%d: fail: %s * %s gave %s expected %s\n", - line, as, bs, ps, cs); - fails++; - - sfree(as); - sfree(bs); - sfree(cs); - sfree(ps); - } - freebn(a); - freebn(b); - freebn(c); - freebn(p); - } else if (!strcmp(buf, "modmul")) { - Bignum a, b, m, c, p; - - if (ptrnum != 4) { - printf("%d: modmul with %d parameters, expected 4\n", - line, ptrnum); - exit(1); - } - a = bignum_from_bytes(ptrs[0], ptrs[1]-ptrs[0]); - b = bignum_from_bytes(ptrs[1], ptrs[2]-ptrs[1]); - m = bignum_from_bytes(ptrs[2], ptrs[3]-ptrs[2]); - c = bignum_from_bytes(ptrs[3], ptrs[4]-ptrs[3]); - p = modmul(a, b, m); - - if (bignum_cmp(c, p) == 0) { - passes++; - } else { - char *as = bignum_decimal(a); - char *bs = bignum_decimal(b); - char *ms = bignum_decimal(m); - char *cs = bignum_decimal(c); - char *ps = bignum_decimal(p); - - printf("%d: fail: %s * %s mod %s gave %s expected %s\n", - line, as, bs, ms, ps, cs); - fails++; - - sfree(as); - sfree(bs); - sfree(ms); - sfree(cs); - sfree(ps); - } - freebn(a); - freebn(b); - freebn(m); - freebn(c); - freebn(p); - } else if (!strcmp(buf, "pow")) { - Bignum base, expt, modulus, expected, answer; - - if (ptrnum != 4) { - printf("%d: pow with %d parameters, expected 4\n", line, ptrnum); - exit(1); - } - - base = bignum_from_bytes(ptrs[0], ptrs[1]-ptrs[0]); - expt = bignum_from_bytes(ptrs[1], ptrs[2]-ptrs[1]); - modulus = bignum_from_bytes(ptrs[2], ptrs[3]-ptrs[2]); - expected = bignum_from_bytes(ptrs[3], ptrs[4]-ptrs[3]); - answer = modpow(base, expt, modulus); - - if (bignum_cmp(expected, answer) == 0) { - passes++; - } else { - char *as = bignum_decimal(base); - char *bs = bignum_decimal(expt); - char *cs = bignum_decimal(modulus); - char *ds = bignum_decimal(answer); - char *ps = bignum_decimal(expected); - - printf("%d: fail: %s ^ %s mod %s gave %s expected %s\n", - line, as, bs, cs, ds, ps); - fails++; - - sfree(as); - sfree(bs); - sfree(cs); - sfree(ds); - sfree(ps); - } - freebn(base); - freebn(expt); - freebn(modulus); - freebn(expected); - freebn(answer); - } else if (!strcmp(buf, "divmod")) { - Bignum n, d, expect_q, expect_r, answer_q, answer_r; - int fail; - - if (ptrnum != 4) { - printf("%d: divmod with %d parameters, expected 4\n", line, ptrnum); - exit(1); - } - - n = bignum_from_bytes(ptrs[0], ptrs[1]-ptrs[0]); - d = bignum_from_bytes(ptrs[1], ptrs[2]-ptrs[1]); - expect_q = bignum_from_bytes(ptrs[2], ptrs[3]-ptrs[2]); - expect_r = bignum_from_bytes(ptrs[3], ptrs[4]-ptrs[3]); - answer_q = bigdiv(n, d); - answer_r = bigmod(n, d); - - fail = FALSE; - if (bignum_cmp(expect_q, answer_q) != 0) { - char *as = bignum_decimal(n); - char *bs = bignum_decimal(d); - char *cs = bignum_decimal(answer_q); - char *ds = bignum_decimal(expect_q); - - printf("%d: fail: %s / %s gave %s expected %s\n", - line, as, bs, cs, ds); - fail = TRUE; - - sfree(as); - sfree(bs); - sfree(cs); - sfree(ds); - } - if (bignum_cmp(expect_r, answer_r) != 0) { - char *as = bignum_decimal(n); - char *bs = bignum_decimal(d); - char *cs = bignum_decimal(answer_r); - char *ds = bignum_decimal(expect_r); - - printf("%d: fail: %s mod %s gave %s expected %s\n", - line, as, bs, cs, ds); - fail = TRUE; - - sfree(as); - sfree(bs); - sfree(cs); - sfree(ds); - } - - freebn(n); - freebn(d); - freebn(expect_q); - freebn(expect_r); - freebn(answer_q); - freebn(answer_r); - - if (fail) - fails++; - else - passes++; - } else { - printf("%d: unrecognised test keyword: '%s'\n", line, buf); - exit(1); - } - - sfree(buf); - sfree(data); - } - - printf("passed %d failed %d total %d\n", passes, fails, passes+fails); - return fails != 0; -} - -#endif diff --git a/testbn.c b/testbn.c new file mode 100644 index 00000000..55471bd2 --- /dev/null +++ b/testbn.c @@ -0,0 +1,265 @@ +/* + * testbn.c: standalone test program for the bignum code. + */ + +/* + * Accepts input on standard input, in the form generated by + * testdata/bignum.py. + */ + +#include +#include +#include + +#include "ssh.h" + +void modalfatalbox(const char *p, ...) +{ + va_list ap; + fprintf(stderr, "FATAL ERROR: "); + va_start(ap, p); + vfprintf(stderr, p, ap); + va_end(ap); + fputc('\n', stderr); + exit(1); +} + +int random_byte(void) +{ + modalfatalbox("random_byte called in testbn"); + return 0; +} + +#define fromxdigit(c) ( (c)>'9' ? ((c)&0xDF) - 'A' + 10 : (c) - '0' ) + +int main(int argc, char **argv) +{ + char *buf; + int line = 0; + int passes = 0, fails = 0; + + while ((buf = fgetline(stdin)) != NULL) { + int maxlen = strlen(buf); + unsigned char *data = snewn(maxlen, unsigned char); + unsigned char *ptrs[5], *q; + int ptrnum; + char *bufp = buf; + + line++; + + q = data; + ptrnum = 0; + + while (*bufp && !isspace((unsigned char)*bufp)) + bufp++; + if (bufp) + *bufp++ = '\0'; + + while (*bufp) { + char *start, *end; + int i; + + while (*bufp && !isxdigit((unsigned char)*bufp)) + bufp++; + start = bufp; + + if (!*bufp) + break; + + while (*bufp && isxdigit((unsigned char)*bufp)) + bufp++; + end = bufp; + + if (ptrnum >= lenof(ptrs)) + break; + ptrs[ptrnum++] = q; + + for (i = -((end - start) & 1); i < end-start; i += 2) { + unsigned char val = (i < 0 ? 0 : fromxdigit(start[i])); + val = val * 16 + fromxdigit(start[i+1]); + *q++ = val; + } + + ptrs[ptrnum] = q; + } + + if (!strcmp(buf, "mul")) { + Bignum a, b, c, p; + + if (ptrnum != 3) { + printf("%d: mul with %d parameters, expected 3\n", line, ptrnum); + exit(1); + } + a = bignum_from_bytes(ptrs[0], ptrs[1]-ptrs[0]); + b = bignum_from_bytes(ptrs[1], ptrs[2]-ptrs[1]); + c = bignum_from_bytes(ptrs[2], ptrs[3]-ptrs[2]); + p = bigmul(a, b); + + if (bignum_cmp(c, p) == 0) { + passes++; + } else { + char *as = bignum_decimal(a); + char *bs = bignum_decimal(b); + char *cs = bignum_decimal(c); + char *ps = bignum_decimal(p); + + printf("%d: fail: %s * %s gave %s expected %s\n", + line, as, bs, ps, cs); + fails++; + + sfree(as); + sfree(bs); + sfree(cs); + sfree(ps); + } + freebn(a); + freebn(b); + freebn(c); + freebn(p); + } else if (!strcmp(buf, "modmul")) { + Bignum a, b, m, c, p; + + if (ptrnum != 4) { + printf("%d: modmul with %d parameters, expected 4\n", + line, ptrnum); + exit(1); + } + a = bignum_from_bytes(ptrs[0], ptrs[1]-ptrs[0]); + b = bignum_from_bytes(ptrs[1], ptrs[2]-ptrs[1]); + m = bignum_from_bytes(ptrs[2], ptrs[3]-ptrs[2]); + c = bignum_from_bytes(ptrs[3], ptrs[4]-ptrs[3]); + p = modmul(a, b, m); + + if (bignum_cmp(c, p) == 0) { + passes++; + } else { + char *as = bignum_decimal(a); + char *bs = bignum_decimal(b); + char *ms = bignum_decimal(m); + char *cs = bignum_decimal(c); + char *ps = bignum_decimal(p); + + printf("%d: fail: %s * %s mod %s gave %s expected %s\n", + line, as, bs, ms, ps, cs); + fails++; + + sfree(as); + sfree(bs); + sfree(ms); + sfree(cs); + sfree(ps); + } + freebn(a); + freebn(b); + freebn(m); + freebn(c); + freebn(p); + } else if (!strcmp(buf, "pow")) { + Bignum base, expt, modulus, expected, answer; + + if (ptrnum != 4) { + printf("%d: pow with %d parameters, expected 4\n", line, ptrnum); + exit(1); + } + + base = bignum_from_bytes(ptrs[0], ptrs[1]-ptrs[0]); + expt = bignum_from_bytes(ptrs[1], ptrs[2]-ptrs[1]); + modulus = bignum_from_bytes(ptrs[2], ptrs[3]-ptrs[2]); + expected = bignum_from_bytes(ptrs[3], ptrs[4]-ptrs[3]); + answer = modpow(base, expt, modulus); + + if (bignum_cmp(expected, answer) == 0) { + passes++; + } else { + char *as = bignum_decimal(base); + char *bs = bignum_decimal(expt); + char *cs = bignum_decimal(modulus); + char *ds = bignum_decimal(answer); + char *ps = bignum_decimal(expected); + + printf("%d: fail: %s ^ %s mod %s gave %s expected %s\n", + line, as, bs, cs, ds, ps); + fails++; + + sfree(as); + sfree(bs); + sfree(cs); + sfree(ds); + sfree(ps); + } + freebn(base); + freebn(expt); + freebn(modulus); + freebn(expected); + freebn(answer); + } else if (!strcmp(buf, "divmod")) { + Bignum n, d, expect_q, expect_r, answer_q, answer_r; + int fail; + + if (ptrnum != 4) { + printf("%d: divmod with %d parameters, expected 4\n", line, ptrnum); + exit(1); + } + + n = bignum_from_bytes(ptrs[0], ptrs[1]-ptrs[0]); + d = bignum_from_bytes(ptrs[1], ptrs[2]-ptrs[1]); + expect_q = bignum_from_bytes(ptrs[2], ptrs[3]-ptrs[2]); + expect_r = bignum_from_bytes(ptrs[3], ptrs[4]-ptrs[3]); + answer_q = bigdiv(n, d); + answer_r = bigmod(n, d); + + fail = FALSE; + if (bignum_cmp(expect_q, answer_q) != 0) { + char *as = bignum_decimal(n); + char *bs = bignum_decimal(d); + char *cs = bignum_decimal(answer_q); + char *ds = bignum_decimal(expect_q); + + printf("%d: fail: %s / %s gave %s expected %s\n", + line, as, bs, cs, ds); + fail = TRUE; + + sfree(as); + sfree(bs); + sfree(cs); + sfree(ds); + } + if (bignum_cmp(expect_r, answer_r) != 0) { + char *as = bignum_decimal(n); + char *bs = bignum_decimal(d); + char *cs = bignum_decimal(answer_r); + char *ds = bignum_decimal(expect_r); + + printf("%d: fail: %s mod %s gave %s expected %s\n", + line, as, bs, cs, ds); + fail = TRUE; + + sfree(as); + sfree(bs); + sfree(cs); + sfree(ds); + } + + freebn(n); + freebn(d); + freebn(expect_q); + freebn(expect_r); + freebn(answer_q); + freebn(answer_r); + + if (fail) + fails++; + else + passes++; + } else { + printf("%d: unrecognised test keyword: '%s'\n", line, buf); + exit(1); + } + + sfree(buf); + sfree(data); + } + + printf("passed %d failed %d total %d\n", passes, fails, passes+fails); + return fails != 0; +} -- 2.45.2