summaryrefslogtreecommitdiff
blob: 98659ce1722b9f637596abb711d6c3ece341678a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
commit 409c6d4006fdea27e746ea397124f98c92a41a92
Author: Joakim Hamren <joakim.hamren@gmail.com>
Date:   Sat Feb 4 04:21:05 2017 +0100

    Fix for overflowing long causing invalid json
    
    This was caused by checking for "__json__" using PyObject_HasAttrString
    which clears the error set by a previous long overflow. Thus this was dependent
    on the order of processing of dict items, which explains why it was
    seemingly random as the dict items are likely ordered by a hash of
    the key.
    
    This fixes GH224 and GH240.

diff --git a/python/objToJSON.c b/python/objToJSON.c
index 8133fb5..adea2f6 100644
--- a/python/objToJSON.c
+++ b/python/objToJSON.c
@@ -226,6 +226,21 @@ static void *PyDateToINT64(JSOBJ _obj, JSONTypeContext *tc, void *outValue, size
   return NULL;
 }
 
+static int PyHasAttrStringPreserveErr(PyObject *obj, const char *attr)
+{
+  int res;
+  PyObject *excType = NULL, *excValue, *excTraceback;
+
+  if (!PyErr_Occurred())
+    return PyObject_HasAttrString(obj, "__json__");
+
+  PyErr_Fetch(&excType, &excValue, &excTraceback);
+  res = PyObject_HasAttrString(obj, "__json__");
+  PyErr_Restore(excType, excValue, excTraceback);
+
+  return res;
+}
+
 static int Tuple_iterNext(JSOBJ obj, JSONTypeContext *tc)
 {
   PyObject *item;
@@ -471,21 +486,21 @@ static int Dict_iterNext(JSOBJ obj, JSONTypeContext *tc)
     GET_TC(tc)->itemName = PyUnicode_AsUTF8String (GET_TC(tc)->itemName);
   }
   else
-    if (!PyString_Check(GET_TC(tc)->itemName))
-    {
-      GET_TC(tc)->itemName = PyObject_Str(GET_TC(tc)->itemName);
+  if (!PyString_Check(GET_TC(tc)->itemName))
+  {
+    GET_TC(tc)->itemName = PyObject_Str(GET_TC(tc)->itemName);
 #if PY_MAJOR_VERSION >= 3
-      itemNameTmp = GET_TC(tc)->itemName;
-      GET_TC(tc)->itemName = PyUnicode_AsUTF8String (GET_TC(tc)->itemName);
-      Py_DECREF(itemNameTmp);
+    itemNameTmp = GET_TC(tc)->itemName;
+    GET_TC(tc)->itemName = PyUnicode_AsUTF8String (GET_TC(tc)->itemName);
+    Py_DECREF(itemNameTmp);
 #endif
-    }
-    else
-    {
-      Py_INCREF(GET_TC(tc)->itemName);
-    }
-    PRINTMARK();
-    return 1;
+  }
+  else
+  {
+    Py_INCREF(GET_TC(tc)->itemName);
+  }
+  PRINTMARK();
+  return 1;
 }
 
 static void Dict_iterEnd(JSOBJ obj, JSONTypeContext *tc)
@@ -728,7 +743,7 @@ static void Object_beginTypeContext (JSOBJ _obj, JSONTypeContext *tc, JSONObject
     return;
   }
   else
-  if (PyString_Check(obj) && !PyObject_HasAttrString(obj, "__json__"))
+  if (PyString_Check(obj) && !PyHasAttrStringPreserveErr(obj, "__json__"))
   {
     PRINTMARK();
     pc->PyTypeToJSON = PyStringToUTF8; tc->type = JT_UTF8;