diff options
author | dkf <donal.k.fellows@manchester.ac.uk> | 2019-04-04 23:08:05 (GMT) |
---|---|---|
committer | dkf <donal.k.fellows@manchester.ac.uk> | 2019-04-04 23:08:05 (GMT) |
commit | 68bc66d5ce6a782cc55d31cbaa515a4b22a11321 (patch) | |
tree | 5a7ba236d9f9e8fac1e8ac247ea502250937c868 /generic/tclLink.c | |
parent | 29e66a4612510aaa8bf5c23bf498507e2d578c3a (diff) | |
download | tcl-68bc66d5ce6a782cc55d31cbaa515a4b22a11321.zip tcl-68bc66d5ce6a782cc55d31cbaa515a4b22a11321.tar.gz tcl-68bc66d5ce6a782cc55d31cbaa515a4b22a11321.tar.bz2 |
Now with fewer memory leaks
Diffstat (limited to 'generic/tclLink.c')
-rw-r--r-- | generic/tclLink.c | 39 |
1 files changed, 27 insertions, 12 deletions
diff --git a/generic/tclLink.c b/generic/tclLink.c index 39ddbdd..616bdaf 100644 --- a/generic/tclLink.c +++ b/generic/tclLink.c @@ -468,32 +468,47 @@ GetUWide( int type; if (TclGetNumberFromObj(NULL, objPtr, &clientData, &type) == TCL_OK) { - if (type == TCL_NUMBER_BIG) { + if (type == TCL_NUMBER_INT) { + *widePtr = *((const Tcl_WideInt *) clientData); + return (*widePtr < 0); + } else if (type == TCL_NUMBER_BIG) { mp_int num; - Tcl_WideUInt scratch, value = 0; + Tcl_WideUInt value = 0; + union { + Tcl_WideUInt value; + unsigned char bytes[sizeof(Tcl_WideUInt)]; + } scratch; unsigned long numBytes = sizeof(Tcl_WideUInt); - unsigned char *bytes = (unsigned char *) &scratch; + unsigned char *bytes = scratch.bytes; Tcl_GetBignumFromObj(NULL, objPtr, &num); - if (num.sign) { - return 1; - } - if (mp_to_unsigned_bin_n(&num, bytes, &numBytes) != MP_OKAY) { + if (num.sign || (MP_OKAY != mp_to_unsigned_bin_n(&num, bytes, + &numBytes))) { + /* + * If the sign bit is set (a negative value) or if the value + * can't possibly fit in the bits of an unsigned wide, there's + * no point in doing further conversion. + */ + mp_clear(&num); return 1; } +#ifdef WORDS_BIGENDIAN while (numBytes-- > 0) { value = (value << CHAR_BIT) | *bytes++; } +#else /* !WORDS_BIGENDIAN */ + value = scratch.value; +#endif /* WORDS_BIGENDIAN */ *uwidePtr = value; + mp_clear(&num); return 0; - } else { - if (Tcl_GetWideIntFromObj(NULL, objPtr, widePtr) == TCL_OK - && (*widePtr >= 0)) { - return 0; - } } } + /* + * Evil edge case fallback. + */ + return (GetInvalidWideFromObj(objPtr, widePtr) != TCL_OK); } |