summaryrefslogtreecommitdiffstats
path: root/generic/tclLink.c
diff options
context:
space:
mode:
authordkf <donal.k.fellows@manchester.ac.uk>2019-04-04 23:08:05 (GMT)
committerdkf <donal.k.fellows@manchester.ac.uk>2019-04-04 23:08:05 (GMT)
commit68bc66d5ce6a782cc55d31cbaa515a4b22a11321 (patch)
tree5a7ba236d9f9e8fac1e8ac247ea502250937c868 /generic/tclLink.c
parent29e66a4612510aaa8bf5c23bf498507e2d578c3a (diff)
downloadtcl-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.c39
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);
}