CVE-2022-41889 (published 2022-11-18T22:15Z)

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.

CVSS v3 base score: 7.5, HIGH (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H)

Weakness information:
cwe_id: CWE-476
cwe_name: NULL Pointer Dereference
description: The product dereferences a pointer that it expects to be valid but is NULL.
extended_description: 
            
            
            
         
         

Fix information:
repo_url: https://github.com/tensorflow/tensorflow
commit_details: repo_url: https://github.com/tensorflow/tensorflow
author: Antonio Sanchez
author_date: 2022-09-26 13:45:03-07:00
msg: 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
repository: repo_url: https://github.com/tensorflow/tensorflow
repo_name: tensorflow/tensorflow
description: An Open Source Machine Learning Framework for Everyone
repo_language: C++
owner: tensorflow
file_changes: filename: pywrap_tfe_src.cc
change_type: ModificationType.MODIFY
diff: @@ -397,11 +397,20 @@ bool SetOpAttrList(TFE_Context* ctx, TFE_Op* op, const char* key,
   const int num_values = PySequence_Size(py_list);
   if (attr_list_sizes != nullptr) (*attr_list_sizes)[key] = num_values;
 
-#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; \
+#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;                                                        \
+    }                                                                      \
   }
 
   if (type == TF_ATTR_STRING) {

programming_language: C++
filename: extract_image_patches_op_test.py
change_type: ModificationType.MODIFY
diff: @@ -17,7 +17,9 @@
 import numpy as np
 
 from tensorflow.python.framework import constant_op
+from tensorflow.python.framework import dtypes
 from tensorflow.python.ops import array_ops
+from tensorflow.python.ops import math_ops
 from tensorflow.python.platform import test
 
 
@@ -139,6 +141,17 @@ class ExtractImagePatches(test.TestCase):
             padding=padding,
             patches=patches)
 
+  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"))
 
 if __name__ == "__main__":
   test.main()

programming_language: Python