Skip to content

[Bug]: TkAgg fails to find Tcl/Tk libraries in Windows for processes with a large number of modules loaded #22378

Closed

Description

@javidcf

Bug summary

When trying to use the TkAgg backend in a Windows process (a Python process itself or another process with Python embedded) that has a large number of modules loaded (over 1024), the following exception might get raised.

RuntimeError: Failed to load Tcl_SetVar

Code for reproduction

# Within a Windows process with a large number of modules loaded
import matplotlib as mpl
mpl.use('TkAgg')

Actual outcome

Loading the TkAgg backend fails with the following error:

RuntimeError: Failed to load Tcl_SetVar

Expected outcome

The TkAgg backend loads correctly.

Additional information

The reason for this error is that the function load_tkinter_funcs, which iterates through each module loaded by the process in search of the ones containing Tcl and Tk functions, calls EnumProcessModules with an output array with a fixed size of 1024. If the process has more than 1024 modules loaded, some of them will not be inspected, and so the code may fail to find it.

Instead, as explained by the documentation of EnumProcessModules, the returned needed array size should be checked:

To determine if the lphModule array is too small to hold all module handles for the process, compare the value returned in lpcbNeeded with the value specified in cb. If lpcbNeeded is greater than cb, increase the size of the array and call EnumProcessModules again.

This implies using dynamically allocated memory. Alternatively, the size of the array could be increased further and hope this pushes away the problem far enough.

In any case, the current code is not safe, as it iterates the array a number of times depending on the needed size, so if that value is greater than the size of the array, the code will accessing memory out of the boundaries of the array. It should only iterate up to the smaller of the needed size and the actual size.

Operating system

Windows 10

Matplotlib Version

3.4.2

Matplotlib Backend

TkAgg

Python version

3.7.7

Jupyter version

No response

Installation

pip

Activity

  1. QuLogic commented on Feb 2, 2022

    @QuLogic
    Member

    In any case, the current code is not safe, as it iterates the array a number of times depending on the needed size, so if that value is greater than the size of the array, the code will accessing memory out of the boundaries of the array. It should only iterate up to the smaller of the needed size and the actual size.

    I didn't write this, but I'm going defer the blame to Microsoft, as their example did not handle resizing the array either. That being said, is it really reading out of bounds, or does the call return an error that the buffer was too small (and thus we check nothing)?

  2. added this to the v3.5.2 milestone on Feb 2, 2022
  3. javidcf commented on Feb 2, 2022

    @javidcf
    Author

    In any case, the current code is not safe, as it iterates the array a number of times depending on the needed size, so if that value is greater than the size of the array, the code will accessing memory out of the boundaries of the array. It should only iterate up to the smaller of the needed size and the actual size.

    I didn't write this, but I'm going defer the blame to Microsoft, as their example did not handle resizing the array either. That being said, is it really reading out of bounds, or does the call return an error that the buffer was too small (and thus we check nothing)?

    Good point about the example, hadn't seen that. Now that you say that, I'm not sure if the function fails or not, I'm not really familiar with the Windows API. In any case, it doesn't work for the use case described anyway.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions