C++ API `GatherV2` aborts with inappropriate input
@Sehun0819 The values in indices should be within the valid range of params along the gather_dim dimension. Accessing invalid indices results in errors. Thank you! @sushreebarsa 
Hi!
Please note that it crashed in the middle of shape inference step, not by being checked status.
Doesn't it need appropriate input checker for preventing crash?
 Hi @Sehun0819 ,

The suspected code pointed is right.The `InferenceContext::UnknownShapeOfRank` calls assertion below.

https://github.com/tensorflow/tensorflow/blob/e193d8ea7776ef5c6f5d769b6fb9c070213e737a/tensorflow/core/framework/shape_inference.cc#L705

The behaviour of `CHECK_GE` is such that it asserts whether `rank` is >=0 and if condition fails it aborts and terminate the program. It will be nice to have functionality like `OP_REQUIRES` which will raise exception instead of abortion.Will look into it.
### Issue type

Bug

### Have you reproduced the bug with TensorFlow Nightly?

Yes

### Source

source

### TensorFlow version

tf 2.17

### Custom code

Yes

### OS platform and distribution

Linux Ubuntu 22.04 LTS

### Mobile device

_No response_

### Python version

3.11.7

### Bazel version

6.5.0

### GCC/compiler version

clang 16

### CUDA/cuDNN version

_No response_

### GPU model and memory

_No response_

### Current behavior?

C++ API `GatherV2` aborts with inappropriate input.
Suspected code location is [here](https://github.com/tensorflow/tensorflow/blob/e193d8ea7776ef5c6f5d769b6fb9c070213e737a/tensorflow/core/ops/array_ops.cc#L1240-L1242),
```C++
          c->set_output(0, c->UnknownShapeOfRank(c->Rank(params_shape) +
                                                 c->Rank(indices_shape) - 1 -
                                                 batch_dims));
```
which calls `UnknownShapeOfRank` with negative value due to lack of validity check.

### Standalone code to reproduce the issue

```C++
#include "tensorflow/cc/framework/scope.h"
#include "tensorflow/core/graph/graph.h"
#include "tensorflow/core/public/session.h"
#include "tensorflow/cc/ops/array_ops.h"
#include "tensorflow/cc/ops/standard_ops.h"

using namespace tensorflow;

int main() {
  SessionOptions options;
  ConfigProto & config = options.config;
  config.set_inter_op_parallelism_threads(1);
  config.set_intra_op_parallelism_threads(1);
  config.set_use_per_session_threads(false);
  std::unique_ptr<tensorflow::Session>
    session(tensorflow::NewSession(options));
  Scope scope = Scope::NewRootScope();

  auto params = ops::RandomUniformInt(scope, {1}, 0, 15);
  auto attrs = 
    ops::GatherV2::Attrs()
      .BatchDims(2);
  auto target = ops::GatherV2(scope.WithOpName("target"), params, 1, 1, attrs);

  GraphDef graph_def;
  TF_CHECK_OK(scope.ToGraphDef(&graph_def));

  Status status = session->Create(graph_def);
  if (!status.ok()) {
    LOG(WARNING) << "Could not create session: " << status.message();
  }

  std::vector<Tensor> outputs;
  status = session->Run({}, {"target"}, {""}, &outputs);
  if (!status.ok()) {
    LOG(WARNING) << "Could not run session: " << status.message();
  }

  return 0;
}
```


### Relevant log output

```shell
2024-02-18 03:14:31.909510: F tensorflow/core/framework/shape_inference.cc:705] Check failed: rank >= 0 (0 vs. -2)rank must not be negative
Aborted (core dumped)
```
