Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
fea2878
Validate scalar shape for input_min/input_max in QuantizeAndDequantizeV3
ayushozha Feb 2, 2026
7003dde
Fix OOB write in MaxPoolGradWithArgmax (CWE-787)
adithyan-ak Apr 7, 2026
9ebce0d
Enforce runtime vector rank invariants in StringNGrams
jmestwa-coder May 19, 2026
61ea1fa
Merge branch 'master' into fix/maxpool-grad-argmax-oob-write
adithyan-ak May 29, 2026
7b7afc0
Add regression test for MaxPoolGradWithArgmax OOB argmax indices
adithyan-ak Jul 2, 2026
145da4b
test: accept graph quantize scalar shape error
ayushozha Jul 5, 2026
832f9e1
handle graph-mode shape inference error in StringNGrams rank test
jmestwa-coder Jul 9, 2026
32772f9
reject empty row_splits when decoding RaggedTensorVariant
madib06ops Jul 17, 2026
d7573bb
use CreateVariantFromRagged helper in RaggedSplitEmpty test
madib06ops Jul 20, 2026
16924cf
fix(scatter_nd): validate updates rank to avoid CHECK-fail crash
Yigtwxx Jul 16, 2026
f22a66e
Validate batch_index rank in Unbatch before accessing its dimensions
vishwakt Jul 23, 2026
448305d
test(scatter_nd): address review feedback on rank-validation tests
Yigtwxx Jul 24, 2026
efadb4b
Validate reverse axes for scalar and empty inputs
vishwakt Aug 13, 2026
86d7965
fix(rnn): bounds check seq_len_max in BlockLSTM ops to prevent OOB ac…
veerjain-1 Aug 15, 2026
c841dac
test: add bounds validation tests for BlockLSTM seq_len_max
veerjain-1 Aug 23, 2026
592bd0d
Merge master and resolve conflicts
veerjain-1 Aug 23, 2026
f8fbb96
fix(test): wrap long lines in rnn_cell_test.py to pass PyLint
veerjain-1 Aug 23, 2026
40ad276
fix(test): update expected error message for seq_len_max bounds check
veerjain-1 Aug 24, 2026
67fa3b0
Validate data rank in Unbatch and index rank in UnbatchGrad
vishwakt Aug 26, 2026
116b81d
Fix integer overflow and type mapping in Unicode operations
opabhijeet May 5, 2026
30b8178
Add missing Tsplits=int32 tests for UnicodeDecodeWithOffsets
opabhijeet May 7, 2026
5a6c469
Trigger CI
opabhijeet May 9, 2026
815924d
Add value assertions for char_values and char_to_byte_starts
opabhijeet Jun 28, 2026
aeb4a60
Fix pylint line-too-long errors
opabhijeet Jun 30, 2026
1edb19c
upgrade offsets to int64 and fix python formatting
opabhijeet Jul 1, 2026
b7f54ac
Fix tensorflow/lite/delegates/ynnpack/attention_bench build in open-s…
vksnk Sep 1, 2026
cf5232b
Reverts 7b34ce2de44d6b34e35ae10d2f5dbd7218e173a9
akuegel Sep 1, 2026
4c493e0
Fix memory leak in GradientTape::ComputeGradient on backward function…
tensorflower-gardener Sep 1, 2026
d31f980
Add support for feature group convolutions (`feature_group_count > 1`…
blakehechtman Sep 1, 2026
8eee663
PR #47176: [ROCM] Wire all MORI collectives through a dedicated Colle…
pemeliya Sep 1, 2026
98d6125
Strip bazel-out prefix from generated #include directives.
tensorflower-gardener Sep 1, 2026
e3ab2a2
[XLA:MSA] Clamp a view use's prefetch deadline to the view's own time
patrick-toulme Sep 1, 2026
2b01994
[IFRT] Add RemapPlan constructor with input_devices_for_output_map an…
junwhanahn Sep 1, 2026
822a287
This is an automatic update to a device compatibility allowlist.
apaiu-dev Sep 1, 2026
fc34c82
Automated Code Change
tensorflower-gardener Sep 1, 2026
22d32c4
Support tuple entry parameters in MakeDataflowConstrainedArguments.
bhatuzdaname Sep 1, 2026
5853a3b
PR #47769: Reject transpose tiles exceeding shared memory during Trit…
mfrancepillois Sep 1, 2026
be9bcee
Allow using higher alignment for dmas for dynamic shape metadata.
pschuh Sep 1, 2026
1e6ebb9
[XLA] Add xla_deduplicate_backend_configs_min_size flag to control ba…
thcmbs Sep 1, 2026
aa0530d
Remove the no-op flow of uploading and using autotune results.
shyamliagrawal Sep 1, 2026
f0f71dc
Replace `TF_ASSERT_OK_AND_ASSIGN` with `ASSERT_OK_AND_ASSIGN` in `pjr…
zacmustin Sep 1, 2026
3cf2b22
Integrate LLVM at llvm/llvm-project@cbc5a226cbf8
tensorflower-gardener Sep 1, 2026
786097d
Merge pull request #125400 from veerjain-1:fix-blocklstmgrad-oob
tensorflower-gardener Sep 1, 2026
2458545
Prefactor for supporting remote tile SPMEM transfers.
emilyfertig Sep 1, 2026
4604684
Merge pull request #123379 from Yigtwxx:fix/scatter-nd-rank-validatio…
tensorflower-gardener Sep 1, 2026
6862b7b
Merge pull request #125269 from vishwakt:fix-reverse-scalar-axis-vali…
tensorflower-gardener Sep 1, 2026
b86b8e5
Merge pull request #123865 from vishwakt:fix-unbatch-index-rank-crash
tensorflower-gardener Sep 1, 2026
f7eabcb
Merge pull request #117891 from opabhijeet:fix-unicode-splits-dtype
tensorflower-gardener Sep 1, 2026
28cb2ac
Merge pull request #123446 from madib06ops:ragged-variant-empty-splits
tensorflower-gardener Sep 1, 2026
d05dcb5
Merge pull request #109355 from ayushozha:fix/quantize-dequantize-v3-…
tensorflower-gardener Sep 1, 2026
fa336cc
Merge pull request #118868 from jmestwa-coder:string-ngrams-runtime-r…
tensorflower-gardener Sep 1, 2026
e22f2b2
[SDY][Bug-Fix] Fix Shardy shard_map export for nested ManualComputati…
Varcho Sep 1, 2026
7be031e
Merge pull request #115326 from adithyan-ak:fix/maxpool-grad-argmax-o…
tensorflower-gardener Sep 2, 2026
9c6fd26
Propagate min/max reduction identity element constraints in Constrain…
bhatuzdaname Sep 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions tensorflow/c/eager/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -273,11 +273,13 @@ tf_cuda_cc_test(
tags = tf_cuda_tests_tags() + ["nomac"],
deps = [
":abstract_context",
":abstract_operation",
":abstract_tensor_handle",
":c_api_experimental",
":c_api_test_util",
":c_api_unified_internal",
":gradients_internal",
":tape",
":unified_api_testutil",
"//tensorflow/c:c_api",
"//tensorflow/c:c_test_util",
Expand All @@ -294,6 +296,8 @@ tf_cuda_cc_test(
"//tensorflow/core:test_main",
"//tensorflow/core/lib/llvm_rtti",
"@com_google_absl//absl/container:flat_hash_set",
"@com_google_absl//absl/log:check",
"@com_google_absl//absl/status",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/types:span",
],
Expand Down Expand Up @@ -1085,6 +1089,7 @@ cc_library(
"//tensorflow/core/config:flags",
"//tensorflow/core/platform:errors",
"//tensorflow/core/platform:types",
"@com_google_absl//absl/container:flat_hash_set",
"@com_google_absl//absl/log",
"@com_google_absl//absl/log:check",
"@com_google_absl//absl/log:vlog_is_on",
Expand Down
16 changes: 13 additions & 3 deletions tensorflow/c/eager/gradients.cc
Original file line number Diff line number Diff line change
Expand Up @@ -214,14 +214,22 @@ absl::Status TapeVSpace::CallBackwardFunction(
const std::vector<int64_t>& unneeded_gradients,
absl::Span<AbstractTensorHandle* const> output_gradients,
absl::Span<AbstractTensorHandle*> result) const {
absl::Status s;
if (gradient_function == nullptr) {
return absl::InvalidArgumentError(absl::StrCat(
s = absl::InvalidArgumentError(absl::StrCat(
"Provided null gradient_function for '", op_type, "'.\n",
"If the intent is to treat this op as non-differentiable consider ",
"using RegisterNotDifferentiable or ",
"NotDifferentiableGradientFunction."));
} else {
s = gradient_function->Compute(ctx_, output_gradients, result);
}
for (AbstractTensorHandle* grad : output_gradients) {
if (grad != nullptr) {
grad->Unref();
}
}
return gradient_function->Compute(ctx_, output_gradients, result);
return s;
}

absl::Status TapeVSpace::BuildOnesLike(const TapeTensor& t,
Expand Down Expand Up @@ -251,7 +259,9 @@ TapeTensor TapeVSpace::TapeTensorFromGradient(AbstractTensorHandle* g) const {
return TapeTensor(g);
}

void TapeVSpace::MarkAsResult(AbstractTensorHandle* gradient) const {}
void TapeVSpace::MarkAsResult(AbstractTensorHandle* gradient) const {
if (gradient) gradient->Ref();
}

void TapeVSpace::DeleteGradient(AbstractTensorHandle* gradient) const {
gradient->Unref();
Expand Down
200 changes: 191 additions & 9 deletions tensorflow/c/eager/gradients_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,29 @@ limitations under the License.
==============================================================================*/
#include "tensorflow/c/eager/gradients.h"

#include <cstdint>
#include <memory>
#include <tuple>
#include <vector>

#include "absl/container/flat_hash_set.h"
#include "absl/log/check.h"
#include "absl/status/status.h"
#include "absl/types/span.h"
#include "tensorflow/c/eager/abstract_context.h"
#include "tensorflow/c/eager/abstract_operation.h"
#include "tensorflow/c/eager/abstract_tensor_handle.h"
#include "tensorflow/c/eager/c_api_experimental.h"
#include "tensorflow/c/eager/c_api_test_util.h"
#include "tensorflow/c/eager/c_api_unified_experimental.h"
#include "tensorflow/c/eager/c_api_unified_experimental_internal.h"
#include "tensorflow/c/eager/gradients_internal.h"
#include "tensorflow/c/eager/tape.h"
#include "tensorflow/c/eager/unified_api_testutil.h"
#include "tensorflow/c/experimental/gradients/array_grad.h"
#include "tensorflow/c/experimental/gradients/math_grad.h"
#include "tensorflow/c/experimental/gradients/not_differentiable.h"
#include "tensorflow/c/experimental/gradients/tape/tape_context.h"
#include "tensorflow/c/experimental/ops/array_ops.h"
#include "tensorflow/c/experimental/ops/math_ops.h"
#include "tensorflow/c/tf_datatype.h"
#include "tensorflow/c/tf_status.h"
#include "tensorflow/c/tf_status_helper.h"
#include "tensorflow/c/tf_tensor.h"
#include "xla/tsl/platform/errors.h"
#include "tensorflow/core/lib/gtl/array_slice.h"
#include "tensorflow/core/lib/llvm_rtti/llvm_rtti.h"
#include "tensorflow/core/platform/errors.h"
#include "tensorflow/core/platform/test.h"
Expand Down Expand Up @@ -123,10 +126,11 @@ absl::Status RecordOperationWithNullGradientFunctionModel(
AbstractTensorHandle* neg_output;
TF_RETURN_IF_ERROR(ops::Neg(ctx, inputs[0], &neg_output, "Neg"));
tape.RecordOperation(inputs, {neg_output}, nullptr, "Neg");
inputs[0]->Ref();
return tape.ComputeGradient(ctx,
/*targets=*/{neg_output},
/*sources=*/inputs,
/*output_gradients=*/{}, outputs);
/*output_gradients=*/{inputs[0]}, outputs);
}

TEST_P(CppGradients, TestRecordOperationWithNullGradientFunctionRaises) {
Expand Down Expand Up @@ -161,6 +165,139 @@ TEST_P(CppGradients, TestRecordOperationWithNullGradientFunctionRaises) {
"or NotDifferentiableGradientFunction.",
s.message());
ASSERT_EQ(nullptr, outputs[0]);
EXPECT_TRUE(x.get()->RefCountIsOne());
}

class DummyGradientFunction : public GradientFunction {
public:
absl::Status Compute(AbstractContext* ctx,
absl::Span<AbstractTensorHandle* const> grad_outputs,
absl::Span<AbstractTensorHandle*> grad_inputs) override {
if (!grad_inputs.empty() && !grad_outputs.empty()) {
grad_inputs[0] = grad_outputs[0];
if (grad_inputs[0]) {
grad_inputs[0]->Ref();
}
}
return absl::OkStatus();
}
};

TEST_P(CppGradients, TestMarkAsResult) {
std::unique_ptr<TF_Status, decltype(&TF_DeleteStatus)> status(
TF_NewStatus(), TF_DeleteStatus);
AbstractContextPtr ctx;
{
AbstractContext* ctx_raw = nullptr;
absl::Status s =
BuildImmediateExecutionContext(std::get<1>(GetParam()), &ctx_raw);
ASSERT_EQ(errors::OK, s.code()) << s.message();
ctx.reset(ctx_raw);
}

AbstractTensorHandlePtr x;
{
AbstractTensorHandle* x_raw = nullptr;
absl::Status s =
TestScalarTensorHandle<float, TF_FLOAT>(ctx.get(), 2.0f, &x_raw);
ASSERT_EQ(errors::OK, s.code()) << s.message();
x.reset(x_raw);
}

std::vector<AbstractTensorHandle*> temp_outputs(1);
AbstractOperationPtr op(ctx.get()->CreateOperation());
ForwardOperation forward_op;
absl::Status s =
Reset(op.get(), "Identity", /*raw_device_name=*/nullptr, &forward_op);
ASSERT_EQ(errors::OK, s.code()) << s.message();
s = AddInput(op.get(), x.get(), &forward_op);
ASSERT_EQ(errors::OK, s.code()) << s.message();
int num_retvals = 1;
s = op->Execute(absl::MakeSpan(temp_outputs), &num_retvals);
ASSERT_EQ(errors::OK, s.code()) << s.message();

Tape tape(/*persistent=*/false);
tape.Watch(x.get());
tape.RecordOperation({x.get()}, temp_outputs, new DummyGradientFunction,
"Identity");

std::vector<AbstractTensorHandle*> outputs(1);
x.get()->Ref(); // Pass ownership of this gradient to ComputeGradient
s = tape.ComputeGradient(ctx.get(),
/*targets=*/temp_outputs,
/*sources=*/{temp_outputs[0]},
/*output_gradients=*/{x.get()},
absl::MakeSpan(outputs));
ASSERT_EQ(errors::OK, s.code());
ASSERT_EQ(x.get(), outputs[0]);
outputs[0]->Unref();
EXPECT_TRUE(x.get()->RefCountIsOne());
}

struct DummyTensor {
int64_t id;
int64_t GetID() const { return id; }
tensorflow::DataType GetDType() const { return tensorflow::DT_FLOAT; }
int* ZerosLike() const { return nullptr; }
};

struct DummyBackwardFunction {};

class MockVSpace
: public eager::VSpace<int, DummyBackwardFunction, DummyTensor> {
public:
mutable int delete_gradient_called_ = 0;

int64_t NumElements(int* tensor) const override { return 1; }
int* AggregateGradients(
gtl::ArraySlice<int*> gradient_tensors) const override {
return gradient_tensors[0];
}
absl::Status CallBackwardFunction(
const std::string& op_type, DummyBackwardFunction* backward_function,
const std::vector<int64_t>& unneeded_gradients,
gtl::ArraySlice<int*> output_gradients,
absl::Span<int*> result) const override {
for (int* g : output_gradients) {
if (g) DeleteGradient(g);
}
return absl::InternalError("Intentional failure");
}
absl::Status BuildOnesLike(const DummyTensor& t,
int** result) const override {
*result = new int(1);
return absl::OkStatus();
}
int64_t TensorId(int* tensor) const override { return 0; }
DummyTensor TapeTensorFromGradient(int* gradient) const override {
return DummyTensor{0};
}
void MarkAsResult(int* gradient) const override {}
void DeleteGradient(int* gradient) const override {
delete_gradient_called_++;
delete gradient;
}
};

TEST(GradientTapeTest, MemoryLeakOnFailure) {
eager::GradientTape<int, DummyBackwardFunction, DummyTensor> tape(
/*persistent=*/false);
tape.Watch(1);

DummyBackwardFunction* bw = new DummyBackwardFunction();
tape.RecordOperation(
"TestOp", {DummyTensor{2}}, {1}, {tensorflow::DT_FLOAT},
[bw]() { return bw; }, [](DummyBackwardFunction* bw) { delete bw; });

MockVSpace vspace;
std::vector<int*> results(1);
absl::Status s =
tape.ComputeGradient(vspace, {2}, {1}, {}, {}, absl::MakeSpan(results),
/*build_default_zeros_grads=*/false);

ASSERT_EQ(error::INTERNAL, s.code());
EXPECT_EQ(1, vspace.delete_gradient_called_)
<< "Expected gradient to be deleted (memory leak if 0)";
}

TEST_P(CppGradients, TestExecuteWithLargerOutputsVectorDoesNotCrash) {
Expand Down Expand Up @@ -235,6 +372,51 @@ INSTANTIATE_TEST_SUITE_P(
/*tfrt*/ ::testing::Values(false),
/*executing_eagerly*/ ::testing::Values(true, false)));
#endif
TEST(GradientTapeTest, TapeVSpaceLeakOnBackwardFunctionError) {
std::unique_ptr<TF_Status, decltype(&TF_DeleteStatus)> status(
TF_NewStatus(), TF_DeleteStatus);
AbstractContextPtr ctx;
{
AbstractContext* ctx_raw = nullptr;
absl::Status s = BuildImmediateExecutionContext(false, &ctx_raw);
ASSERT_EQ(errors::OK, s.code()) << s.message();
ctx.reset(ctx_raw);
}

AbstractTensorHandlePtr x;
{
AbstractTensorHandle* x_raw = nullptr;
absl::Status s =
TestScalarTensorHandle<float, TF_FLOAT>(ctx.get(), 2.0f, &x_raw);
ASSERT_EQ(errors::OK, s.code()) << s.message();
x.reset(x_raw);
}

Tape tape(/*persistent=*/false);
tape.Watch(x.get());
AbstractTensorHandle* neg_output;
absl::Status s = ops::Neg(ctx.get(), x.get(), &neg_output, "Neg");
ASSERT_EQ(errors::OK, s.code()) << s.message();
AbstractTensorHandle* neg_output2;
s = ops::Neg(ctx.get(), x.get(), &neg_output2, "Neg2");
ASSERT_EQ(errors::OK, s.code()) << s.message();

tape.RecordOperation({x.get()}, {neg_output, neg_output2}, nullptr, "Neg");
x.get()->Ref();

std::vector<AbstractTensorHandle*> outputs;
s = tape.ComputeGradient(ctx.get(),
/*targets=*/{neg_output},
/*sources=*/{},
/*output_gradients=*/{x.get()},
absl::MakeSpan(outputs));
ASSERT_EQ(error::INVALID_ARGUMENT, s.code());
neg_output->Unref();
neg_output2->Unref();

EXPECT_TRUE(x.get()->RefCountIsOne());
}

} // namespace
} // namespace internal
} // namespace gradients
Expand Down
4 changes: 0 additions & 4 deletions tensorflow/c/eager/parallel_device/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,8 @@ cc_library(
"//tensorflow/c/eager:c_api",
"//tensorflow/c/eager:c_api_experimental",
"//tensorflow/c/eager:tfe_tensorhandle_internal",
"//tensorflow/core/platform:status",
"@com_google_absl//absl/status",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/types:optional",
"@com_google_absl//absl/types:variant",
],
)
Expand All @@ -105,7 +103,6 @@ cc_library(
"//tensorflow/core:framework",
"//tensorflow/core:lib",
"@com_google_absl//absl/base:core_headers",
"@com_google_absl//absl/memory",
"@com_google_absl//absl/status",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/synchronization",
Expand All @@ -131,7 +128,6 @@ tf_cc_test(
"//tensorflow/core:test",
"//tensorflow/core:test_main",
"//tensorflow/core/common_runtime/eager:context",
"//tensorflow/core/platform:status",
"@com_google_absl//absl/status",
"@com_google_googletest//:gtest_main",
],
Expand Down
13 changes: 11 additions & 2 deletions tensorflow/c/eager/tape.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@ limitations under the License.
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

#include "absl/container/flat_hash_set.h"
#include "absl/log/check.h"
#include "absl/log/log.h"
#include "absl/log/vlog_is_on.h"
Expand Down Expand Up @@ -812,6 +814,13 @@ GradientTape<Gradient, BackwardFunction, TapeTensor>::ComputeGradient(
trace.backward_function_deleter(trace.backward_function);
}
if (!s.ok()) {
for (const auto& pair : gradients) {
for (Gradient* g : pair.second) {
if (g != nullptr) {
vspace.DeleteGradient(g);
}
}
}
return s;
}
} else {
Expand Down Expand Up @@ -892,7 +901,7 @@ GradientTape<Gradient, BackwardFunction, TapeTensor>::ComputeGradient(
source_tensor_ids.size(), " found ", result.size(),
" in call to Tape::ComputeGradient.");
}
std::unordered_set<int64_t> used_gradient_ids(source_tensor_ids.size());
absl::flat_hash_set<int64_t> used_gradient_ids(source_tensor_ids.size());
for (int i = 0; i < source_tensor_ids.size(); i++) {
int64_t tensor_id = source_tensor_ids[i];
auto grad_it = gradients.find(tensor_id);
Expand Down Expand Up @@ -967,7 +976,7 @@ ForwardAccumulator<Gradient, BackwardFunction, TapeTensor>::ForwardpropFromTape(
gtl::MakeCleanup([&call_state] { call_state.backward_tape = nullptr; });
std::vector<Gradient*> forwardprop_aids;
std::vector<int64_t> sources;
std::unordered_set<int64_t> sources_set;
absl::flat_hash_set<int64_t> sources_set;
sources.reserve(output_tensors.size());
for (const TapeTensor& output_tensor : output_tensors) {
// Ownership of `aid` transferred to CallBackwardFunction below.
Expand Down
3 changes: 2 additions & 1 deletion tensorflow/compiler/aot/tfcompile.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,8 @@ def _tf_library(
sed_replace = (
"-e \"s|{{TFCOMPILE_HEADER}}|$(location " + header_file + ")|g\" " +
"-e \"s|{{TFCOMPILE_CPP_CLASS}}|" + cpp_class + "|g\" " +
"-e \"s|{{TFCOMPILE_NAME}}|" + no_ns_name + "|g\" "
"-e \"s|{{TFCOMPILE_NAME}}|" + no_ns_name + "|g\" " +
"-e \"s!bazel-out/[^/]*/(bin|genfiles)/!!g\" "
)

if gen_test:
Expand Down
Loading
Loading