CVE-2022-41889 (Python, published 2022-11-18T22:15Z)
Description: value: TensorFlow is an open source platform for machine learning. If a list of quantized tensors is assigned to an attribute, the pywrap code fails to parse the tensor and returns a `nullptr`, which is not caught. An example can be seen in `tf.compat.v1.extract_volume_patches` by passing in quantized tensors as input `ksizes`. We have patched the issue in GitHub commit e9e95553e5411834d215e6770c81a83a3d0866ce. The fix will be included in TensorFlow 2.11. We will also cherrypick this commit on TensorFlow 2.10.1, 2.9.3, and TensorFlow 2.8.4, as these are also affected and still in supported range.
Severity: nan (CVSS v3 base score: 7.5)
Weakness: CWE-476 \u2014 NULL Pointer Dereference
The product dereferences a pointer that it expects to be valid but is NULL.
Repository: https://github.com/tensorflow/tensorflow
Files changed:
tensorflow/python/eager/pywrap_tfe_src.cc
tensorflow/python/kernel_tests/image_ops/extract_image_patches_op_test.py
Commit message: Fix pywrap attribute read security vulnerability.

If a list of quantized tensors is assigned to an attribute, the pywrap code was failing to
parse the tensor and returning a `nullptr`, which wasn't caught.  Here we check the return
value and set an appropriate error status.

PiperOrigin-RevId: 476981029


Vulnerable code:
#define PARSE_LIST(c_type, parse_fn)                                      \
  std::unique_ptr<c_type[]> values(new c_type[num_values]);               \
  for (int i = 0; i < num_values; ++i) {                                  \
    tensorflow::Safe_PyObjectPtr py_value(PySequence_ITEM(py_list, i));   \
    if (!parse_fn(key, py_value.get(), status, &values[i])) return false; \

Fixed code:
#define PARSE_LIST(c_type, parse_fn)                                       \
  std::unique_ptr<c_type[]> values(new c_type[num_values]);                \
  for (int i = 0; i < num_values; ++i) {                                   \
    tensorflow::Safe_PyObjectPtr py_value(PySequence_ITEM(py_list, i));    \
    if (py_value == nullptr) {                                             \
      TF_SetStatus(status, TF_INVALID_ARGUMENT,                            \
                   tensorflow::strings::StrCat(                            \
                       "Expecting sequence of " #c_type " for attr ", key, \
                       ", got ", py_list->ob_type->tp_name)                \
                       .c_str());                                          \
      return false;                                                        \
    } else if (!parse_fn(key, py_value.get(), status, &values[i])) {       \
      return false;                                                        \
    }                                                                      \
from tensorflow.python.framework import dtypes
from tensorflow.python.ops import math_ops
  def testInvalidAttributes(self):
    """Test for passing weird things into ksizes."""
    with self.assertRaisesRegex(TypeError, "Expected list"):
      image = constant_op.constant([0.0])
      ksizes = math_ops.cast(
          constant_op.constant(dtype=dtypes.int16, value=[[1, 4], [5, 2]]),
          dtype=dtypes.qint16)
      strides = [1, 1, 1, 1]
      self.evaluate(
          array_ops.extract_image_patches(
              image, ksizes=ksizes, strides=strides, padding="SAME"))