Fix #1679: "0x" was taken as a valid integer literal.
Fixes the tokenizer, tokenize.py and int() to reject this.
Patches by Malte Helmert.
diff --git a/Python/mystrtoul.c b/Python/mystrtoul.c
index f007057..a02992f 100644
--- a/Python/mystrtoul.c
+++ b/Python/mystrtoul.c
@@ -112,27 +112,40 @@
 
 	/* check for leading 0 or 0x for auto-base or base 16 */
 	switch (base) {
-		case 0:		/* look for leading 0, 0x or 0X */
-			if (*str == '0') {
-				++str;
-				if (*str == 'x' || *str == 'X') {
-					++str;
-					base = 16;
+	case 0:		/* look for leading 0, 0x or 0X */
+		if (*str == '0') {
+			++str;
+			if (*str == 'x' || *str == 'X') {
+				/* there must be at least one digit after 0x */
+				if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 16) {
+					if (ptr)
+						*ptr = str;
+					return 0;
 				}
-				else
-					base = 8;
+				++str;
+				base = 16;
 			}
 			else
-				base = 10;
-			break;
+				base = 8;
+		}
+		else
+			base = 10;
+		break;
 
-		case 16:	/* skip leading 0x or 0X */
-			if (*str == '0') {
+	case 16:	/* skip leading 0x or 0X */
+		if (*str == '0') {
+			++str;
+			if (*str == 'x' || *str == 'X') {
+				/* there must be at least one digit after 0x */
+				if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 16) {
+					if (ptr)
+						*ptr = str;
+					return 0;
+				}
 				++str;
-				if (*str == 'x' || *str == 'X')
-					++str;
 			}
-			break;
+		}
+		break;
 	}
 
 	/* catch silly bases */