From f4739140e3d664b7a5211991d8a81006de0f4df8 Mon Sep 17 00:00:00 2001 From: JustAnotherArchivist Date: Thu, 7 Apr 2022 04:31:47 +0000 Subject: [PATCH] Fix ref counting on non-string dict keys For bytes, there was an extraneous INCREF; PyIter_Next returns a new reference. For other non-strings, the original itemName before converting to a string was never dereferenced. Fixes #419 --- python/objToJSON.c | 6 ++---- tests/test_ujson.py | 4 ++-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/python/objToJSON.c b/python/objToJSON.c index 743e6f29..10970d37 100644 --- a/python/objToJSON.c +++ b/python/objToJSON.c @@ -254,15 +254,13 @@ static int Dict_iterNext(JSOBJ obj, JSONTypeContext *tc) return 1; } + itemNameTmp = GET_TC(tc)->itemName; GET_TC(tc)->itemName = PyObject_Str(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); } - else - { - Py_INCREF(GET_TC(tc)->itemName); - } PRINTMARK(); return 1; } diff --git a/tests/test_ujson.py b/tests/test_ujson.py index b0b39479..69d76bc8 100644 --- a/tests/test_ujson.py +++ b/tests/test_ujson.py @@ -239,11 +239,11 @@ def test_encode_dict_values_ref_counting(): @pytest.mark.skipif( hasattr(sys, "pypy_version_info"), reason="PyPy uses incompatible GC" ) -def test_encode_dict_key_ref_counting(): +@pytest.mark.parametrize("key", ["key", b"key", 1, True, None]) +def test_encode_dict_key_ref_counting(key): import gc gc.collect() - key = "key" data = {key: "abc"} ref_count = sys.getrefcount(key) ujson.dumps(data)