X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/e111b81fd51dc9e942c7eff1a94045a81b34cc9f..819a22b356a0113860c30b12cf42ba8616a15d1a:/sshbn.c diff --git a/sshbn.c b/sshbn.c index 14cdd05e..728b6fa0 100644 --- a/sshbn.c +++ b/sshbn.c @@ -9,6 +9,20 @@ #include "misc.h" +/* + * Usage notes: + * * Do not call the DIVMOD_WORD macro with expressions such as array + * subscripts, as some implementations object to this (see below). + * * Note that none of the division methods below will cope if the + * quotient won't fit into BIGNUM_INT_BITS. Callers should be careful + * to avoid this case. + * If this condition occurs, in the case of the x86 DIV instruction, + * an overflow exception will occur, which (according to a correspondent) + * will manifest on Windows as something like + * 0xC0000095: Integer overflow + * The C variant won't give the right answer, either. + */ + #if defined __GNUC__ && defined __i386__ typedef unsigned long BignumInt; typedef unsigned long long BignumDblInt; @@ -27,26 +41,16 @@ typedef unsigned __int64 BignumDblInt; #define BIGNUM_TOP_BIT 0x80000000UL #define BIGNUM_INT_BITS 32 #define MUL_WORD(w1, w2) ((BignumDblInt)w1 * w2) -typedef struct { - unsigned __int32 quot; - unsigned __int32 remd; -} msvc_quorem; -static __declspec(naked) msvc_quorem __stdcall msvc_divmod( - unsigned __int32 hi, - unsigned __int32 lo, - unsigned __int32 w) -{ - __asm { - mov edx, dword ptr [esp+4] - mov eax, dword ptr [esp+8] - div dword ptr [esp+12] - ret 12 - }; -} +/* Note: MASM interprets array subscripts in the macro arguments as + * assembler syntax, which gives the wrong answer. Don't supply them. + * */ #define DIVMOD_WORD(q, r, hi, lo, w) do { \ - const msvc_quorem qr = msvc_divmod((hi), (lo), (w)); \ - (q) = qr.quot; (r) = qr.remd; \ -} while (0) + __asm mov edx, hi \ + __asm mov eax, lo \ + __asm div w \ + __asm mov r, edx \ + __asm mov q, eax \ +} while(0) #else typedef unsigned short BignumInt; typedef unsigned long BignumDblInt; @@ -230,7 +234,10 @@ static void internal_mod(BignumInt *a, int alen, */ q = BIGNUM_INT_MASK; } else { - DIVMOD_WORD(q, r, h, a[i], m0); + /* Macro doesn't want an array subscript expression passed + * into it (see definition), so use a temporary. */ + BignumInt tmplo = a[i]; + DIVMOD_WORD(q, r, h, tmplo, m0); /* Refine our estimate of q by looking at h:a[i]:a[i+1] / m0:m1 */