longobject.c:
    Replaced PyLong_{As,From}{Unsigned,}LongLong guts with calls
    to _PyLong_{As,From}ByteArray.
_testcapimodule.c:
    Added strong tests of PyLong_{As,From}{Unsigned,}LongLong.

Fixes SF bug #432552 PyLong_AsLongLong() problems.
Possible bugfix candidate, but the fix relies on code added to longobject
to support the new q/Q structmodule format codes.
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
index a49c60a..06602e9 100644
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -177,28 +177,171 @@
 /* Basic sanity checks for PyLong_{As, From}{Unsigned,}LongLong(). */
 
 static PyObject *
+raise_test_longlong_error(const char* msg)
+{
+	return raiseTestError("test_longlong_api", msg);
+}
+
+#define UNBIND(X)  Py_DECREF(X); (X) = NULL
+
+static PyObject *
 test_longlong_api(PyObject* self, PyObject* args)
 {
-	/* unsigned LONG_LONG uinput, uoutput; */
-	LONG_LONG input, output;
+	const int NBITS = SIZEOF_LONG_LONG * 8;
+	unsigned LONG_LONG base;
 	PyObject *pyresult;
+	int i;
 
         if (!PyArg_ParseTuple(args, ":test_longlong_api"))
                 return NULL;
 
-	input = 0;
-	pyresult = PyLong_FromLongLong(input);
-	if (pyresult == NULL)
-		return raiseTestError("test_longlong_api",
-				      "unexpected null result");
-	output = PyLong_AsLongLong(pyresult);
-	if (output == (LONG_LONG)-1 && PyErr_Occurred())
-		return raiseTestError("test_longlong_api",
-				      "unexpected -1 result");
-	if (output != input)
-		return raiseTestError("test_longlong_api",
-				       "output != input");
-	Py_DECREF(pyresult);
+
+	/* Note:  This test lets PyObjects leak if an error is raised.  Since
+	   an error should never be raised, leaks are impossible <wink>. */
+
+	/* Test native -> PyLong -> native roundtrip identity.
+	 * Generate all powers of 2, and test them and their negations,
+	 * plus the numbers +-1 off from them.
+	 */
+	base = 1;
+	for (i = 0;
+	     i < NBITS + 1;  /* on last, base overflows to 0 */
+	     ++i, base <<= 1)
+	{
+		int j;
+		for (j = 0; j < 6; ++j) {
+			LONG_LONG in, out;
+			unsigned LONG_LONG uin, uout;
+
+			/* For 0, 1, 2 use base; for 3, 4, 5 use -base */
+			uin = j < 3 ? base
+				    : (unsigned LONG_LONG)(-(LONG_LONG)base);
+
+			/* For 0 & 3, subtract 1.
+			 * For 1 & 4, leave alone.
+			 * For 2 & 5, add 1.
+			 */
+			uin += (unsigned LONG_LONG)(LONG_LONG)(j % 3 - 1);
+
+			pyresult = PyLong_FromUnsignedLongLong(uin);
+			if (pyresult == NULL)
+				return raise_test_longlong_error(
+					"unsigned unexpected null result");
+
+			uout = PyLong_AsUnsignedLongLong(pyresult);
+			if (uout == (unsigned LONG_LONG)-1 && PyErr_Occurred())
+				return raise_test_longlong_error(
+					"unsigned unexpected -1 result");
+			if (uout != uin)
+				return raise_test_longlong_error(
+					"unsigned output != input");
+			UNBIND(pyresult);
+
+			in = (LONG_LONG)uin;
+			pyresult = PyLong_FromLongLong(in);
+			if (pyresult == NULL)
+				return raise_test_longlong_error(
+					"signed unexpected null result");
+
+			out = PyLong_AsLongLong(pyresult);
+			if (out == (LONG_LONG)-1 && PyErr_Occurred())
+				return raise_test_longlong_error(
+					"signed unexpected -1 result");
+			if (out != in)
+				return raise_test_longlong_error(
+					"signed output != input");
+			UNBIND(pyresult);
+		}
+	}
+
+	/* Overflow tests.  The loop above ensured that all limit cases that
+	 * should not overflow don't overflow, so all we need to do here is
+	 * provoke one-over-the-limit cases (not exhaustive, but sharp).
+	 */
+	{
+		PyObject *one, *x, *y;
+		LONG_LONG out;
+		unsigned LONG_LONG uout;
+
+		one = PyLong_FromLong(1);
+		if (one == NULL)
+			return raise_test_longlong_error(
+				"unexpected NULL from PyLong_FromLong");
+
+		/* Unsigned complains about -1? */
+		x = PyNumber_Negative(one);
+		if (x == NULL)
+			return raise_test_longlong_error(
+				"unexpected NULL from PyNumber_Negative");
+
+		uout = PyLong_AsUnsignedLongLong(x);
+		if (uout != (unsigned LONG_LONG)-1 || !PyErr_Occurred())
+			return raise_test_longlong_error(
+				"PyLong_AsUnsignedLongLong(-1) didn't "
+				"complain");
+		PyErr_Clear();
+		UNBIND(x);
+
+		/* Unsigned complains about 2**NBITS? */
+		y = PyLong_FromLong((long)NBITS);
+		if (y == NULL)
+			return raise_test_longlong_error(
+				"unexpected NULL from PyLong_FromLong");
+
+		x = PyNumber_Lshift(one, y); /* 1L << NBITS, == 2**NBITS */
+		UNBIND(y);
+		if (x == NULL)
+			return raise_test_longlong_error(
+				"unexpected NULL from PyNumber_Lshift");
+
+  		uout = PyLong_AsUnsignedLongLong(x);
+		if (uout != (unsigned LONG_LONG)-1 || !PyErr_Occurred())
+			return raise_test_longlong_error(
+				"PyLong_AsUnsignedLongLong(2**NBITS) didn't "
+				"complain");
+		PyErr_Clear();
+
+		/* Signed complains about 2**(NBITS-1)?
+		   x still has 2**NBITS. */
+		y = PyNumber_Rshift(x, one); /* 2**(NBITS-1) */
+		UNBIND(x);
+		if (y == NULL)
+			return raise_test_longlong_error(
+				"unexpected NULL from PyNumber_Rshift");
+
+		out = PyLong_AsLongLong(y);
+		if (out != (LONG_LONG)-1 || !PyErr_Occurred())
+			return raise_test_longlong_error(
+				"PyLong_AsLongLong(2**(NBITS-1)) didn't "
+				"complain");
+		PyErr_Clear();
+
+		/* Signed complains about -2**(NBITS-1)-1?;
+		   y still has 2**(NBITS-1). */
+		x = PyNumber_Negative(y);  /* -(2**(NBITS-1)) */
+		UNBIND(y);
+		if (x == NULL)
+			return raise_test_longlong_error(
+				"unexpected NULL from PyNumber_Negative");
+
+		y = PyNumber_Subtract(x, one); /* -(2**(NBITS-1))-1 */
+		UNBIND(x);
+		if (y == NULL)
+			return raise_test_longlong_error(
+				"unexpected NULL from PyNumber_Subtract");
+
+		out = PyLong_AsLongLong(y);
+		if (out != (LONG_LONG)-1 || !PyErr_Occurred())
+			return raise_test_longlong_error(
+				"PyLong_AsLongLong(-2**(NBITS-1)-1) didn't "
+				"complain");
+		PyErr_Clear();
+		UNBIND(y);
+
+		Py_XDECREF(x);
+		Py_XDECREF(y);
+		Py_DECREF(one);
+	}
 
 	Py_INCREF(Py_None);
 	return Py_None;
diff --git a/Objects/longobject.c b/Objects/longobject.c
index 17af671..615d497 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -522,168 +522,83 @@
 }
 
 #ifdef HAVE_LONG_LONG
-/*
- * LONG_LONG support by Chris Herborth (chrish@qnx.com)
- *
- * For better or worse :-), I tried to follow the coding style already
- * here.
+
+/* Initial LONG_LONG support by Chris Herborth (chrish@qnx.com), later
+ * rewritten to use the newer PyLong_{As,From}ByteArray API.
  */
 
-/* Create a new long int object from a C LONG_LONG int */
+#define IS_LITTLE_ENDIAN *(char*)&one != '\0'
+
+/* Create a new long int object from a C LONG_LONG int. */
 
 PyObject *
 PyLong_FromLongLong(LONG_LONG ival)
 {
-#if SIZEOF_LONG_LONG == SIZEOF_LONG
-	/* In case the compiler is faking it. */
-	return PyLong_FromLong( (long)ival );
-#else
-	if ((LONG_LONG)LONG_MIN <= ival && ival <= (LONG_LONG)LONG_MAX) {
-		return PyLong_FromLong( (long)ival );
-	}
-	else if (0 <= ival && ival <= (unsigned LONG_LONG)ULONG_MAX) {
-		return PyLong_FromUnsignedLong( (unsigned long)ival );
-	}
-	else {
-		/* Assume a C LONG_LONG fits in at most 10 'digits'.
-		 * Should be OK if we're assuming long fits in 5.
-		 */
-		PyLongObject *v = _PyLong_New(10);
-
-		if (v != NULL) {
-			unsigned LONG_LONG t = ival;
-			int i;
-			if (ival < 0) {
-				t = -ival;
-				v->ob_size = -(v->ob_size);
-  			}
-
-			for (i = 0; i < 10; i++) {
-				v->ob_digit[i] = (digit) (t & MASK);
-				t >>= SHIFT;
-			}
-
-			v = long_normalize(v);
-		}
-
-		return (PyObject *)v;
-	}
-#endif
+	LONG_LONG bytes = ival;
+	int one = 1;
+	return _PyLong_FromByteArray(
+			(unsigned char *)&bytes,
+			SIZEOF_LONG_LONG, IS_LITTLE_ENDIAN, 1);
 }
 
-/* Create a new long int object from a C unsigned LONG_LONG int */
+/* Create a new long int object from a C unsigned LONG_LONG int. */
+
 PyObject *
 PyLong_FromUnsignedLongLong(unsigned LONG_LONG ival)
 {
-#if SIZEOF_LONG_LONG == SIZEOF_LONG
-	/* In case the compiler is faking it. */
-	return PyLong_FromUnsignedLong( (unsigned long)ival );
-#else
-	if( ival <= (unsigned LONG_LONG)ULONG_MAX ) {
-		return PyLong_FromUnsignedLong( (unsigned long)ival );
-	}
-	else {
-		/* Assume a C long fits in at most 10 'digits'. */
-		PyLongObject *v = _PyLong_New(10);
-
-		if (v != NULL) {
-			unsigned LONG_LONG t = ival;
-			int i;
-			for (i = 0; i < 10; i++) {
-				v->ob_digit[i] = (digit) (t & MASK);
-				t >>= SHIFT;
-			}
-
-			v = long_normalize(v);
-		}
-
-		return (PyObject *)v;
-	}
-#endif
+	unsigned LONG_LONG bytes = ival;
+	int one = 1;
+	return _PyLong_FromByteArray(
+			(unsigned char *)&bytes,
+			SIZEOF_LONG_LONG, IS_LITTLE_ENDIAN, 0);
 }
 
 /* Get a C LONG_LONG int from a long int object.
-   Returns -1 and sets an error condition if overflow occurs. */
+   Return -1 and set an error if overflow occurs. */
 
 LONG_LONG
 PyLong_AsLongLong(PyObject *vv)
 {
-#if SIZEOF_LONG_LONG == SIZEOF_LONG
-	/* In case the compiler is faking it. */
-	return (LONG_LONG)PyLong_AsLong( vv );
-#else
-	register PyLongObject *v;
-	LONG_LONG x, prev;
-	int i, sign;
-	
+	LONG_LONG bytes;
+	int one = 1;
+	int res;
+
 	if (vv == NULL || !PyLong_Check(vv)) {
 		PyErr_BadInternalCall();
 		return -1;
 	}
 
-	v = (PyLongObject *)vv;
-	i = v->ob_size;
-	sign = 1;
-	x = 0;
+	res = _PyLong_AsByteArray(
+			(PyLongObject *)vv, (unsigned char *)&bytes,
+			SIZEOF_LONG_LONG, IS_LITTLE_ENDIAN, 1);
 
-	if (i < 0) {
-		sign = -1;
-		i = -(i);
-	}
-
-	while (--i >= 0) {
-		prev = x;
-		x = (x << SHIFT) + v->ob_digit[i];
-		if ((x >> SHIFT) != prev) {
-			PyErr_SetString(PyExc_OverflowError,
-				"long int too long to convert");
-			return -1;
-		}
-	}
-
-	return x * sign;
-#endif
+	return (LONG_LONG)(res < 0 ? res : bytes);
 }
 
+/* Get a C unsigned LONG_LONG int from a long int object.
+   Return -1 and set an error if overflow occurs. */
+
 unsigned LONG_LONG
 PyLong_AsUnsignedLongLong(PyObject *vv)
 {
-#if SIZEOF_LONG_LONG == 4
-	/* In case the compiler is faking it. */
-	return (unsigned LONG_LONG)PyLong_AsUnsignedLong( vv );
-#else
-	register PyLongObject *v;
-	unsigned LONG_LONG x, prev;
-	int i;
-	
+	unsigned LONG_LONG bytes;
+	int one = 1;
+	int res;
+
 	if (vv == NULL || !PyLong_Check(vv)) {
 		PyErr_BadInternalCall();
-		return (unsigned LONG_LONG) -1;
+		return -1;
 	}
 
-	v = (PyLongObject *)vv;
-	i = v->ob_size;
-	x = 0;
+	res = _PyLong_AsByteArray(
+			(PyLongObject *)vv, (unsigned char *)&bytes,
+			SIZEOF_LONG_LONG, IS_LITTLE_ENDIAN, 0);
 
-	if (i < 0) {
-		PyErr_SetString(PyExc_OverflowError,
-			   "can't convert negative value to unsigned long");
-		return (unsigned LONG_LONG) -1;
-	}
-
-	while (--i >= 0) {
-		prev = x;
-		x = (x << SHIFT) + v->ob_digit[i];
-		if ((x >> SHIFT) != prev) {
-			PyErr_SetString(PyExc_OverflowError,
-				"long int too long to convert");
-			return (unsigned LONG_LONG) -1;
-		}
-	}
-
-	return x;
-#endif
+	return (unsigned LONG_LONG)(res < 0 ? res : bytes);
 }
+
+#undef IS_LITTLE_ENDIAN
+
 #endif /* HAVE_LONG_LONG */