`DecisionTreeClassifier` does not handle `Nan`

### Describe the bug

We implemented Decision Tree classifiers for a graduate course in Machine Learning. Part of my test suite compares the performance of my `DecisionTree` to the `sklearn.DecisionTreeClassifier` on the Iris dataset, with a specified amount of the data replaced with `NaN`, to test the performance on a dataset with missing values. This test-module worked without issue for several weeks, that is until I updated my Debian 11 system to Debian 12, which updated python and its libraries as well. Now when I try to train the ` sklearn.DecisionTreeClassifier`, I am receiving the following error message:
```
ValueError: Input X contains NaN.
DecisionTreeClassifier does not accept missing values encoded as NaN natively. For supervised learning, you might want to consider sklearn.ensemble.HistGradientBoostingClassifier and Regressor which accept missing values encoded as NaNs natively. Alternatively, it is possible to preprocess the data, for instance by using an imputer transformer in a pipeline or drop samples with missing values. See https://scikit-learn.org/stable/modules/impute.html You can find a list of all estimators that handle NaN values at the following page: https://scikit-learn.org/stable/modules/impute.html#estimators-that-handle-nan-values
``` 
This is not right: as before, section 1.10.8 of the  [current documentation ](https://scikit-learn.org/stable/modules/tree.html#tree-missing-value-support) on Decision Trees states that
> `DecisionTreeClassifier` and `DecisionTreeRegressor` have built-in support for missing values when splitter='best' and criterion is 'gini', 'entropy’, or 'log_loss', for classification or 'squared_error', 'friedman_mse', or 'poisson' for regression.
For each potential threshold on the non-missing data, the splitter will evaluate the split with all the missing values going to the left node or the right node.

and goes on to demonstrate these facilities using `np.nan` in the sample data. Similarly, [the general documentation on imputation](https://scikit-learn.org/stable/modules/impute.html#estimators-that-handle-nan-values) lists `DecisionTreeClassifier` as an estimator that handles `NaN` values.

### Steps/Code to Reproduce

```
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import train_test_split
import numpy as np
rng = np.random.default_rng(17)

    
def train_iris_missing(percent:float, k_nearest:int = 4, test_size:float = .5, min_leaf:int = 1) -> dict:
    # Load the Iris data
    iris = load_iris()
    classes = np.unique(iris.target)
    IRIS_N, IRIS_D = iris.data.shape
    
    var_names = iris.feature_names
    for i, name in enumerate(var_names):
        # graphviz does not allow parentheses in labels
        var_names[i] = var_names[i].replace('(','[').replace(')', ']')

    # Modify Iris such that {percent} of the fields are missing
    for i in range(IRIS_D):
        missing = rng.choice(
            np.arange(IRIS_N), size=int(np.floor(IRIS_N*percent)), 
            replace=False, shuffle=False,
        )
        mask = np.zeros(shape=(IRIS_N,), dtype=bool)
        mask[missing] = True
        iris.data[mask, i] = np.nan

    # Split the data 
    X_train, X_test, Y_train, Y_test = train_test_split(
        iris.data, iris.target, test_size=test_size, random_state=23
    )

    # Reference -- fully expanded {DecisionTreeClassifier}
    T_sk= DecisionTreeClassifier(
        criterion="gini", splitter='best', random_state=23, min_samples_leaf = min_leaf
    )
    T_sk.fit(X_train, Y_train)
    return {
        "sklearn.DecisionTreeClassifier":T_sk, 
        "X_train":X_train,
        "X_test":X_test,
        "Y_train":Y_train,
        "Y_test":Y_test,
        "var_names":var_names,
        "class_names":iris.target_names
    }

iris95 = train_iris_missing(percent=.05)
T_sk = iris95["sklearn.DecisionTreeClassifier"]
T_sk.score(iris95['X_test'], iris95['Y_test'])
```

### Expected Results

The `DecisionTreeClassifier` is trained on the modified Iris data and returned, along with the data, without error. 

### Actual Results

```
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[26], line 3
      1 # Iris[ ~ 1/20 missing]
      2 # --------------------------------------------------------------------------------------------
----> 3 iris95 = train_iris_missing(percent=.05)
      4 T_sk = iris95["sklearn.DecisionTreeClassifier"]
      5 T_sk.score(iris95['X_test'], iris95['Y_test'])

Cell In[25], line 39, in train_iris_missing(percent, k_nearest, test_size, min_leaf)
     35 # Reference -- fully expanded {DecisionTreeClassifier}
     36 T_sk= DecisionTreeClassifier(
     37     criterion="gini", splitter='best', random_state=23, min_samples_leaf = min_leaf
     38 )
---> 39 T_sk.fit(X_train, Y_train)
     40 return {
     41     "sklearn.DecisionTreeClassifier":T_sk, 
     42     "X_train":X_train,
   (...)
     47     "class_names":iris.target_names
     48 }

File ~/.local/lib/python3.11/site-packages/sklearn/tree/_classes.py:889, in DecisionTreeClassifier.fit(self, X, y, sample_weight, check_input)
    859 def fit(self, X, y, sample_weight=None, check_input=True):
    860     """Build a decision tree classifier from the training set (X, y).
    861 
    862     Parameters
   (...)
    886         Fitted estimator.
    887     """
--> 889     super().fit(
    890         X,
    891         y,
    892         sample_weight=sample_weight,
    893         check_input=check_input,
    894     )
    895     return self

File ~/.local/lib/python3.11/site-packages/sklearn/tree/_classes.py:186, in BaseDecisionTree.fit(self, X, y, sample_weight, check_input)
    184 check_X_params = dict(dtype=DTYPE, accept_sparse="csc")
    185 check_y_params = dict(ensure_2d=False, dtype=None)
--> 186 X, y = self._validate_data(
    187     X, y, validate_separately=(check_X_params, check_y_params)
    188 )
    189 if issparse(X):
    190     X.sort_indices()

File ~/.local/lib/python3.11/site-packages/sklearn/base.py:579, in BaseEstimator._validate_data(self, X, y, reset, validate_separately, **check_params)
    577 if "estimator" not in check_X_params:
    578     check_X_params = {**default_check_params, **check_X_params}
--> 579 X = check_array(X, input_name="X", **check_X_params)
    580 if "estimator" not in check_y_params:
    581     check_y_params = {**default_check_params, **check_y_params}

File ~/.local/lib/python3.11/site-packages/sklearn/utils/validation.py:921, in check_array(array, accept_sparse, accept_large_sparse, dtype, order, copy, force_all_finite, ensure_2d, allow_nd, ensure_min_samples, ensure_min_features, estimator, input_name)
    915         raise ValueError(
    916             "Found array with dim %d. %s expected <= 2."
    917             % (array.ndim, estimator_name)
    918         )
    920     if force_all_finite:
--> 921         _assert_all_finite(
    922             array,
    923             input_name=input_name,
    924             estimator_name=estimator_name,
    925             allow_nan=force_all_finite == "allow-nan",
    926         )
    928 if ensure_min_samples > 0:
    929     n_samples = _num_samples(array)

File ~/.local/lib/python3.11/site-packages/sklearn/utils/validation.py:161, in _assert_all_finite(X, allow_nan, msg_dtype, estimator_name, input_name)
    144 if estimator_name and input_name == "X" and has_nan_error:
    145     # Improve the error message on how to handle missing values in
    146     # scikit-learn.
    147     msg_err += (
    148         f"\n{estimator_name} does not accept missing values"
    149         " encoded as NaN natively. For supervised learning, you might want"
   (...)
    159         "#estimators-that-handle-nan-values"
    160     )
--> 161 raise ValueError(msg_err)

ValueError: Input X contains NaN.
DecisionTreeClassifier does not accept missing values encoded as NaN natively. For supervised learning, you might want to consider sklearn.ensemble.HistGradientBoostingClassifier and Regressor which accept missing values encoded as NaNs natively. Alternatively, it is possible to preprocess the data, for instance by using an imputer transformer in a pipeline or drop samples with missing values. See https://scikit-learn.org/stable/modules/impute.html You can find a list of all estimators that handle NaN values at the following page: https://scikit-learn.org/stable/modules/impute.html#estimators-that-handle-nan-values
```

### Versions

```shell
System:
    python: 3.11.2 (main, Mar 18 2023, 15:28:58) [GCC 10.2.1 20210110]
executable: /usr/local/bin/python3
   machine: Linux-6.1.0-18-amd64-x86_64-with-glibc2.36

Python dependencies:
      sklearn: 1.2.2
          pip: 24.0
   setuptools: 65.5.0
        numpy: 1.24.3
        scipy: 1.11.3
       Cython: 3.0.8
       pandas: 2.1.4
   matplotlib: 3.7.1
       joblib: 1.3.2
threadpoolctl: 3.2.0

Built with OpenMP: True

threadpoolctl info:
       user_api: blas
   internal_api: openblas
    num_threads: 8
         prefix: libopenblas
       filepath: /home/nikolay/.local/lib/python3.11/site-packages/numpy.libs/libopenblas64_p-r0-15028c96.3.21.so
        version: 0.3.21
threading_layer: pthreads
   architecture: Haswell

       user_api: openmp
   internal_api: openmp
    num_threads: 8
         prefix: libgomp
       filepath: /home/nikolay/.local/lib/python3.11/site-packages/scikit_learn.libs/libgomp-a34b3233.so.1.0.0
        version: None

       user_api: blas
   internal_api: openblas
    num_threads: 8
         prefix: libopenblas
       filepath: /home/nikolay/.local/lib/python3.11/site-packages/scipy.libs/libopenblasp-r0-23e5df77.3.21.dev.so
        version: 0.3.21.dev
threading_layer: pthreads
   architecture: Haswell
```
```

COMMENT:
you're using an old sklearn. sklearn=1.4.2 supports missing values.

Labels: Bug, Needs Triage