Skip to content

Commit

Permalink
pythongh-101830: Fix Tcl_Obj to string conversion
Browse files Browse the repository at this point in the history
Accessing the Tkinter object's string representation no longer converts
the underlying Tcl object to a string on Windows.
  • Loading branch information
serhiy-storchaka committed Jun 22, 2024
1 parent 4717aaa commit 2d31fa7
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 21 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Accessing the :mod:`tkinter` object's string representation no longer converts
the underlying Tcl object to a string on Windows.
46 changes: 25 additions & 21 deletions Modules/_tkinter.c
Original file line number Diff line number Diff line change
Expand Up @@ -493,24 +493,28 @@ unicodeFromTclString(const char *s)
}

static PyObject *
unicodeFromTclObj(Tcl_Obj *value)
unicodeFromTclObj(TkappObject *tkapp, Tcl_Obj *value)
{
Tcl_Size len;
#if USE_TCL_UNICODE
int byteorder = NATIVE_BYTEORDER;
const Tcl_UniChar *u = Tcl_GetUnicodeFromObj(value, &len);
if (sizeof(Tcl_UniChar) == 2)
return PyUnicode_DecodeUTF16((const char *)u, len * 2,
"surrogatepass", &byteorder);
else if (sizeof(Tcl_UniChar) == 4)
return PyUnicode_DecodeUTF32((const char *)u, len * 4,
"surrogatepass", &byteorder);
else
Py_UNREACHABLE();
#else
if (value->typePtr != NULL && tkapp != NULL &&
(value->typePtr == tkapp->StringType ||
value->typePtr == tkapp->UTF32StringType))
{
int byteorder = NATIVE_BYTEORDER;
const Tcl_UniChar *u = Tcl_GetUnicodeFromObj(value, &len);
if (sizeof(Tcl_UniChar) == 2)
return PyUnicode_DecodeUTF16((const char *)u, len * 2,
"surrogatepass", &byteorder);
else if (sizeof(Tcl_UniChar) == 4)
return PyUnicode_DecodeUTF32((const char *)u, len * 4,
"surrogatepass", &byteorder);
else
Py_UNREACHABLE();
}
#endif
const char *s = Tcl_GetStringFromObj(value, &len);
return unicodeFromTclStringAndSize(s, len);
#endif
}

/*[clinic input]
Expand Down Expand Up @@ -793,7 +797,7 @@ PyTclObject_string(PyObject *_self, void *ignored)
{
PyTclObject *self = (PyTclObject *)_self;
if (!self->string) {
self->string = unicodeFromTclObj(self->value);
self->string = unicodeFromTclObj(NULL, self->value);
if (!self->string)
return NULL;
}
Expand All @@ -808,7 +812,7 @@ PyTclObject_str(PyObject *_self)
return Py_NewRef(self->string);
}
/* XXX Could cache result if it is non-ASCII. */
return unicodeFromTclObj(self->value);
return unicodeFromTclObj(NULL, self->value);
}

static PyObject *
Expand Down Expand Up @@ -1143,7 +1147,7 @@ FromObj(TkappObject *tkapp, Tcl_Obj *value)
Tcl_Interp *interp = Tkapp_Interp(tkapp);

if (value->typePtr == NULL) {
return unicodeFromTclObj(value);
return unicodeFromTclObj(tkapp, value);
}

if (value->typePtr == tkapp->BooleanType ||
Expand Down Expand Up @@ -1208,7 +1212,7 @@ FromObj(TkappObject *tkapp, Tcl_Obj *value)
if (value->typePtr == tkapp->StringType ||
value->typePtr == tkapp->UTF32StringType)
{
return unicodeFromTclObj(value);
return unicodeFromTclObj(tkapp, value);
}

if (tkapp->BignumType == NULL &&
Expand Down Expand Up @@ -1308,7 +1312,7 @@ Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, Tcl_Size *pobjc)
static PyObject *
Tkapp_UnicodeResult(TkappObject *self)
{
return unicodeFromTclObj(Tcl_GetObjResult(self->interp));
return unicodeFromTclObj(self, Tcl_GetObjResult(self->interp));
}


Expand All @@ -1327,7 +1331,7 @@ Tkapp_ObjectResult(TkappObject *self)
res = FromObj(self, value);
Tcl_DecrRefCount(value);
} else {
res = unicodeFromTclObj(value);
res = unicodeFromTclObj(self, value);
}
return res;
}
Expand Down Expand Up @@ -1860,7 +1864,7 @@ GetVar(TkappObject *self, PyObject *args, int flags)
res = FromObj(self, tres);
}
else {
res = unicodeFromTclObj(tres);
res = unicodeFromTclObj(self, tres);
}
}
LEAVE_OVERLAP_TCL
Expand Down Expand Up @@ -2307,7 +2311,7 @@ PythonCmd(ClientData clientData, Tcl_Interp *interp,

for (i = 0; i < (objc - 1); i++) {
PyObject *s = objargs ? FromObj(data->self, objv[i + 1])
: unicodeFromTclObj(objv[i + 1]);
: unicodeFromTclObj(data->self, objv[i + 1]);
if (!s) {
Py_DECREF(args);
return PythonCmd_Error(interp);
Expand Down

0 comments on commit 2d31fa7

Please sign in to comment.