Vulnerability: Use after free in `DecodePng` kernel ### Impact
A malicious user can cause a use after free behavior when [decoding PNG images](https://github.com/tensorflow/tensorflow/blob/a1320ec1eac186da1d03f033109191f715b2b130/tensorflow/core/kernels/image/decode_image_op.cc#L339-L346):
```cc
if (/* ... error conditions ... */) {
  png::CommonFreeDecode(&decode);
  OP_REQUIRES(context, false,
              errors::InvalidArgument("PNG size too large for int: ",
                                      decode.width, " by ", decode.height));
}   
```
After `png::CommonFreeDecode(&decode)` gets called, the values of `decode.width` and `decode.height` are in an unspecified state.

### Patches
We have patched the issue in GitHub commit [e746adbfcfee15e9cfdb391ff746c765b99bdf9b](https://github.com/tensorflow/tensorflow/commit/e746adbfcfee15e9cfdb391ff746c765b99bdf9b).

The fix will be included in TensorFlow 2.8.0. We will also cherrypick this commit on TensorFlow 2.7.1, TensorFlow 2.6.3, and TensorFlow 2.5.3, as these are also affected and still in supported range.

### For more information
Please consult [our security guide](https://github.com/tensorflow/tensorflow/blob/master/SECURITY.md) for more information regarding the security model and how to contact us with issues and questions.
Vulnerability ID: GHSA-24x4-6qmh-88qg
CWE: CWE-416
Severity score: 7.6
Project: https://github.com/tensorflow/tensorflow
Published: 2022-02-09
File: tensorflow/core/kernels/image/decode_image_op.cc
Commit message: Prevent use after free in `DecodePng` kernel.

We are cleaning up the memory in `decode` and then we are using an `OP_REQUIRES` to check an invariant on the `decode` data.

PiperOrigin-RevId: 409299145
Change-Id: I4eb93aaca52483eb202e89b78df07fbb2f6cb254
Commit author: Mihai Maruseac

Vulnerable version (before fix):
 class DecodeImageV2Op : public OpKernel {     if (width != static_cast<int64_t>(decode.width) || width <= 0 ||         width >= (1LL << 27) || height != static_cast<int64_t>(decode.height) ||         height <= 0 || height >= (1LL << 27) || total_size >= (1LL << 29)) {       png::CommonFreeDecode(&decode);       OP_REQUIRES(context, false,                   errors::InvalidArgument("PNG size too large for int: ",                                           decode.width, " by ", decode.height));

Fixed version (after fix):
 class DecodeImageV2Op : public OpKernel {     if (width != static_cast<int64_t>(decode.width) || width <= 0 ||         width >= (1LL << 27) || height != static_cast<int64_t>(decode.height) ||         height <= 0 || height >= (1LL << 27) || total_size >= (1LL << 29)) {       OP_REQUIRES(context, false,                   errors::InvalidArgument("PNG size too large for int: ",                                           decode.width, " by ", decode.height));

Patch:
patch: @@ -339,7 +339,6 @@ class DecodeImageV2Op : public OpKernel {
     if (width != static_cast<int64_t>(decode.width) || width <= 0 ||
         width >= (1LL << 27) || height != static_cast<int64_t>(decode.height) ||
         height <= 0 || height >= (1LL << 27) || total_size >= (1LL << 29)) {
-      png::CommonFreeDecode(&decode);
       OP_REQUIRES(context, false,
                   errors::InvalidArgument("PNG size too large for int: ",
                                           decode.width, " by ", decode.height));
path: tensorflow/core/kernels/image/decode_image_op.cc