Repository: pandas-dev/pandas
File: pandas/_libs/src/vendored/ujson/python/objToJSON.c (C)

Code before:
  }

  tc->type = JT_OBJECT;
  pc->iterBegin = Dir_iterBegin;
  pc->iterEnd = Dir_iterEnd;
  pc->iterNext = Dir_iterNext;
  pc->iterGetValue = Dir_iterGetValue;
  pc->iterGetName = Dir_iterGetName;
  return;

INVALID:
  tc->type = JT_INVALID;
  PyObject_Free(tc->prv);
  tc->prv = NULL;
  return;
}

static void Object_endTypeContext(JSOBJ Py_UNUSED(obj), JSONTypeContext *tc) {
  if (tc->prv) {
    Py_XDECREF(GET_TC(tc)->newObj);
    GET_TC(tc)->newObj = NULL;
    NpyArr_freeLabels(GET_TC(tc)->rowLabels, GET_TC(tc)->rowLabelsLen);
    GET_TC(tc)->rowLabels = NULL;
    NpyArr_freeLabels(GET_TC(tc)->columnLabels, GET_TC(tc)->columnLabelsLen);
    GET_TC(tc)->columnLabels = NULL;
    PyObject_Free((void *)GET_TC(tc)->cStr);
    GET_TC(tc)->cStr = NULL;
    PyObject_Free(tc->prv);
    tc->prv = NULL;
  }
}

static const char *Object_getStringValue(JSOBJ obj, JSONTypeContext *tc,
                                         size_t *_outLen) {
  return GET_TC(tc)->PyTypeToUTF8(obj, tc, _outLen);
}

static JSINT64 Object_getLongValue(JSOBJ Py_UNUSED(obj), JSONTypeContext *tc) {
  return GET_TC(tc)->longValue;
}

static double Object_getDoubleValue(JSOBJ Py_UNUSED(obj), JSONTypeContext *tc) {
  return GET_TC(tc)->doubleValue;
}

static const char *Object_getBigNumStringValue(JSOBJ obj, JSONTypeContext *tc,
                                               size_t *_outLen) {
  PyObject *repr = PyObject_Str(obj);
  const char *str = PyUnicode_AsUTF8AndSize(repr, (Py_ssize_t *)_outLen);
  char *bytes = PyObject_Malloc(*_outLen + 1);
  memcpy(bytes, str, *_outLen + 1);

Review comment (bug):
I'm not too sure about this approach - generally the CPython API only wants you to call this function when you've allocated with the corresponding function(s)

https://docs.python.org/3/c-api/memory.html#c.PyObject_Free

> Frees the memory block pointed to by p, which must have been returned by a previous call to [PyObject_Malloc()](https://docs.python.org/3/c-api/memory.html#c.PyObject_Malloc), [PyObject_Realloc()](https://docs.python.org/3/c-api/memory.html#c.PyObject_Realloc) or [PyObject_Calloc()](https://docs.python.org/3/c-api/memory.html#c.PyObject_Calloc). Otherwise, or if PyObject_Free(p) has been called before, undefined behavior occurs.


Code after:
    Object_invokeDefaultHandler(obj, enc);
    goto INVALID;
  }

  tc->type = JT_OBJECT;
  pc->iterBegin = Dir_iterBegin;
  pc->iterEnd = Dir_iterEnd;
  pc->iterNext = Dir_iterNext;
  pc->iterGetValue = Dir_iterGetValue;
  pc->iterGetName = Dir_iterGetName;
  return;

INVALID:
  tc->type = JT_INVALID;
  PyObject_Free(tc->prv);
  tc->prv = NULL;
  return;
}

static void Object_endTypeContext(JSOBJ Py_UNUSED(obj), JSONTypeContext *tc) {
  if (tc->prv) {
    Py_XDECREF(GET_TC(tc)->newObj);
    GET_TC(tc)->newObj = NULL;
    NpyArr_freeLabels(GET_TC(tc)->rowLabels, GET_TC(tc)->rowLabelsLen);
    GET_TC(tc)->rowLabels = NULL;
    NpyArr_freeLabels(GET_TC(tc)->columnLabels, GET_TC(tc)->columnLabelsLen);
    GET_TC(tc)->columnLabels = NULL;
    PyObject_Free(GET_TC(tc)->cStr);
    GET_TC(tc)->cStr = NULL;
    PyObject_Free(tc->prv);
    tc->prv = NULL;
  }
}

static const char *Object_getStringValue(JSOBJ obj, JSONTypeContext *tc,
                                         size_t *_outLen) {
  return GET_TC(tc)->PyTypeToUTF8(obj, tc, _outLen);
}

static JSINT64 Object_getLongValue(JSOBJ Py_UNUSED(obj), JSONTypeContext *tc) {
  return GET_TC(tc)->longValue;
}

static double Object_getDoubleValue(JSOBJ Py_UNUSED(obj), JSONTypeContext *tc) {
  return GET_TC(tc)->doubleValue;
}

static const char *Object_getBigNumStringValue(JSOBJ obj, JSONTypeContext *tc,
                                               size_t *_outLen) {
  PyObject *repr = PyObject_Str(obj);
  const char *str = PyUnicode_AsUTF8AndSize(repr, (Py_ssize_t *)_outLen);