Skip to content

Fix MobileNetV3 Preprocess - #46105

Merged
copybara-service[bot] merged 1 commit into
tensorflow:masterfrom
junhyukso:patch-1
Jan 8, 2021
Merged

copybara-service[bot] merged 1 commit into
tensorflow:masterfrom
junhyukso:patch-1

Conversation

@junhyukso

Copy link
Copy Markdown
Contributor

I measured Top1-Acc of ImageNet pretrained MobileNetV3Large model in tensorflow/tensorflow/python/keras/applications/mobilenet_v3.py , but 65% is measured.

After changing preprocess layer

x = layers.Rescaling(1. / 255.)(x)

to

x = layers.Rescaling(scale=1./127.5, offset=-1.)(x)

can measure 72.5% Top1-Acc.

Fix normalize preprocess( 0~1 -> -1~1)
@google-ml-butler google-ml-butler Bot added the size:XS CL Change Size: Extra Small label Jan 2, 2021
@google-cla

google-cla Bot commented Jan 2, 2021

Copy link
Copy Markdown

Thanks for your pull request. It looks like this may be your first contribution to a Google open source project (if not, look below for help). Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

📝 Please visit https://cla.developers.google.com/ to sign.

Once you've signed (or fixed any issues), please reply here with @googlebot I signed it! and we'll verify it.


What to do if you already signed the CLA

Individual signers
Corporate signers

ℹ️ Googlers: Go here for more info.

@google-cla google-cla Bot added the cla: no label Jan 2, 2021
@junhyukso

Copy link
Copy Markdown
Contributor Author

@googlebot I signed it!

@google-cla google-cla Bot added cla: yes and removed cla: no labels Jan 2, 2021
@gbaned gbaned self-assigned this Jan 4, 2021
@gbaned gbaned added the comp:keras Keras related issues label Jan 4, 2021
@gbaned
gbaned self-requested a review January 4, 2021 04:02
@gbaned gbaned added the awaiting review Pull request awaiting review label Jan 5, 2021

@fchollet fchollet left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks for the fix.

@google-ml-butler google-ml-butler Bot added kokoro:force-run Tests on submitted change ready to pull PR ready for merge process labels Jan 7, 2021
@kokoro-team kokoro-team removed the kokoro:force-run Tests on submitted change label Jan 7, 2021
@gbaned gbaned removed the awaiting review Pull request awaiting review label Jan 8, 2021
@copybara-service
copybara-service Bot merged commit 4bb8259 into tensorflow:master Jan 8, 2021
copybara-service Bot pushed a commit that referenced this pull request Jul 24, 2026
…ment::FromProto

Imported from GitHub PR openxla/xla#46105

## Problem

`BufferAssignment::FromProto` passes `assignee.offset()` and `assignee.size()` from a deserialized `BufferAllocationProto.Assigned` proto directly to `BufferAllocation::AddAssignment` without checking for negative values.

The guards inside `AddAssignment` are:
```cpp
CHECK_LE(offset, size_)        // checks offset <= allocation.size()
CHECK_LE(offset + size, size_) // checks offset + size <= allocation.size()
```

These `CHECK_LE` guards are **bypassed by negative int64 values**: `-1 <= 1024` is true for any real allocation, so a negative offset passes both checks and gets stored in `assigned_buffers_`.

The stored negative offset is later used in LLVM IR codegen (`ir_emitter.cc`):
```cpp
tempbuf_address_base + b()->getInt64(slice.offset())
```
With `offset = -1`, this produces a pointer one byte before the allocation — an out-of-bounds address.

## Attack Surface

Reachable from `CpuAotLoader::LoadAotCompilationResult(serialized_aot_result)` where `serialized_aot_result` is a user-supplied serialized AOT executable. The proto fields `offset` and `size` are both `int64` in `hlo.proto`, so negative values are fully valid at the wire level.

## Relationship to PR #44653

PR #44653 (`2840cd3`) fixed `Slice::FromProto` with:
```cpp
if (proto.offset() < 0 || proto.size() < 0) {
  return absl::OutOfRangeError(...);
}
```

This PR applies the **same fix** to `BufferAssignment::FromProto` → `AddAssignment` path, which handles `Assigned` buffers in `BufferAllocationProto` — the sibling that the previous fix missed.

## Fix

Added a pre-validation check in `BufferAssignment::FromProto` before calling `AddAssignment`:

```cpp
if (assignee.offset() < 0 || assignee.size() < 0) {
  return absl::OutOfRangeError(absl::StrCat(
      "BufferAssignment proto contains an assigned buffer with negative ",
      "offset or size: logical_buffer_id=", logical_buffer_id,
      " offset=", assignee.offset(), " size=", assignee.size()));
}
```

## Testing

Two new test cases in `buffer_assignment_test.cc`:
- `BufferAssignmentFromProtoTest.RejectsNegativeOffset`: confirms `offset=-1` bypasses `CHECK_LE` guards (proving the vulnerability) and documents that the fix must reject it before reaching `AddAssignment`
- `BufferAssignmentFromProtoTest.RejectsNegativeSize`: same for `size=-1`

---

*Disclosure: this contribution was authored with the aid of an AI coding assistant and reviewed before submission.*
Copybara import of the project:

--
6fab2ecd47988e30cfe195becfaecdb641479e8c by prasanna8585 <[email protected]>:

[XLA] Validate assigned buffer offset/size in BufferAssignment::FromProto

BufferAssignment::FromProto passes assignee.offset() and assignee.size()
from a deserialized BufferAllocationProto.Assigned proto directly to
BufferAllocation::AddAssignment without checking for negative values.

The CHECK_LE guards in AddAssignment are bypassed by negative int64 values:
  CHECK_LE(-1, 1024) = true  (for any real allocation)
  CHECK_LE(-1 + 4, 1024) = true

So a negative offset is stored in assigned_buffers_ and later used in LLVM
IR codegen (ir_emitter.cc) as:
  tempbuf_address_base + b()->getInt64(slice.offset())
With offset=-1 this is an out-of-bounds address.

This mirrors the fix applied to Slice::FromProto in PR #44653 (2840cd3),
which fixed the thunk deserialization path but missed this sibling path
in BufferAssignment::FromProto.

Fix: add an explicit negative check before calling AddAssignment,
returning absl::OutOfRangeError for negative offset or size values.

Add two regression tests confirming the bypass behavior and documenting
the required fix behavior.

Merging this change closes #46105

FUTURE_COPYBARA_INTEGRATE_REVIEW=openxla/xla#46105 from prasanna8585:fix/buffer-assignment-from-proto-negative-offset 6fab2ecd47988e30cfe195becfaecdb641479e8c
PiperOrigin-RevId: 952638612
copybara-service Bot pushed a commit that referenced this pull request Jul 27, 2026
…ment::FromProto

Imported from GitHub PR openxla/xla#46105

## Problem

`BufferAssignment::FromProto` passes `assignee.offset()` and `assignee.size()` from a deserialized `BufferAllocationProto.Assigned` proto directly to `BufferAllocation::AddAssignment` without checking for negative values.

The guards inside `AddAssignment` are:
```cpp
CHECK_LE(offset, size_)        // checks offset <= allocation.size()
CHECK_LE(offset + size, size_) // checks offset + size <= allocation.size()
```

These `CHECK_LE` guards are **bypassed by negative int64 values**: `-1 <= 1024` is true for any real allocation, so a negative offset passes both checks and gets stored in `assigned_buffers_`.

The stored negative offset is later used in LLVM IR codegen (`ir_emitter.cc`):
```cpp
tempbuf_address_base + b()->getInt64(slice.offset())
```
With `offset = -1`, this produces a pointer one byte before the allocation — an out-of-bounds address.

## Attack Surface

Reachable from `CpuAotLoader::LoadAotCompilationResult(serialized_aot_result)` where `serialized_aot_result` is a user-supplied serialized AOT executable. The proto fields `offset` and `size` are both `int64` in `hlo.proto`, so negative values are fully valid at the wire level.

## Relationship to PR #44653

PR #44653 (`2840cd3`) fixed `Slice::FromProto` with:
```cpp
if (proto.offset() < 0 || proto.size() < 0) {
  return absl::OutOfRangeError(...);
}
```

This PR applies the **same fix** to `BufferAssignment::FromProto` → `AddAssignment` path, which handles `Assigned` buffers in `BufferAllocationProto` — the sibling that the previous fix missed.

## Fix

Added a pre-validation check in `BufferAssignment::FromProto` before calling `AddAssignment`:

```cpp
if (assignee.offset() < 0 || assignee.size() < 0) {
  return absl::OutOfRangeError(absl::StrCat(
      "BufferAssignment proto contains an assigned buffer with negative ",
      "offset or size: logical_buffer_id=", logical_buffer_id,
      " offset=", assignee.offset(), " size=", assignee.size()));
}
```

## Testing

Two new test cases in `buffer_assignment_test.cc`:
- `BufferAssignmentFromProtoTest.RejectsNegativeOffset`: confirms `offset=-1` bypasses `CHECK_LE` guards (proving the vulnerability) and documents that the fix must reject it before reaching `AddAssignment`
- `BufferAssignmentFromProtoTest.RejectsNegativeSize`: same for `size=-1`

---

*Disclosure: this contribution was authored with the aid of an AI coding assistant and reviewed before submission.*
Copybara import of the project:

--
6fab2ecd47988e30cfe195becfaecdb641479e8c by prasanna8585 <[email protected]>:

[XLA] Validate assigned buffer offset/size in BufferAssignment::FromProto

BufferAssignment::FromProto passes assignee.offset() and assignee.size()
from a deserialized BufferAllocationProto.Assigned proto directly to
BufferAllocation::AddAssignment without checking for negative values.

The CHECK_LE guards in AddAssignment are bypassed by negative int64 values:
  CHECK_LE(-1, 1024) = true  (for any real allocation)
  CHECK_LE(-1 + 4, 1024) = true

So a negative offset is stored in assigned_buffers_ and later used in LLVM
IR codegen (ir_emitter.cc) as:
  tempbuf_address_base + b()->getInt64(slice.offset())
With offset=-1 this is an out-of-bounds address.

This mirrors the fix applied to Slice::FromProto in PR #44653 (2840cd3),
which fixed the thunk deserialization path but missed this sibling path
in BufferAssignment::FromProto.

Fix: add an explicit negative check before calling AddAssignment,
returning absl::OutOfRangeError for negative offset or size values.

Add two regression tests confirming the bypass behavior and documenting
the required fix behavior.

Merging this change closes #46105

FUTURE_COPYBARA_INTEGRATE_REVIEW=openxla/xla#46105 from prasanna8585:fix/buffer-assignment-from-proto-negative-offset 6fab2ecd47988e30cfe195becfaecdb641479e8c
PiperOrigin-RevId: 952638612
copybara-service Bot pushed a commit that referenced this pull request Jul 27, 2026
…ment::FromProto

Imported from GitHub PR openxla/xla#46105

## Problem

`BufferAssignment::FromProto` passes `assignee.offset()` and `assignee.size()` from a deserialized `BufferAllocationProto.Assigned` proto directly to `BufferAllocation::AddAssignment` without checking for negative values.

The guards inside `AddAssignment` are:
```cpp
CHECK_LE(offset, size_)        // checks offset <= allocation.size()
CHECK_LE(offset + size, size_) // checks offset + size <= allocation.size()
```

These `CHECK_LE` guards are **bypassed by negative int64 values**: `-1 <= 1024` is true for any real allocation, so a negative offset passes both checks and gets stored in `assigned_buffers_`.

The stored negative offset is later used in LLVM IR codegen (`ir_emitter.cc`):
```cpp
tempbuf_address_base + b()->getInt64(slice.offset())
```
With `offset = -1`, this produces a pointer one byte before the allocation — an out-of-bounds address.

## Attack Surface

Reachable from `CpuAotLoader::LoadAotCompilationResult(serialized_aot_result)` where `serialized_aot_result` is a user-supplied serialized AOT executable. The proto fields `offset` and `size` are both `int64` in `hlo.proto`, so negative values are fully valid at the wire level.

## Relationship to PR #44653

PR #44653 (`2840cd3`) fixed `Slice::FromProto` with:
```cpp
if (proto.offset() < 0 || proto.size() < 0) {
  return absl::OutOfRangeError(...);
}
```

This PR applies the **same fix** to `BufferAssignment::FromProto` → `AddAssignment` path, which handles `Assigned` buffers in `BufferAllocationProto` — the sibling that the previous fix missed.

## Fix

Added a pre-validation check in `BufferAssignment::FromProto` before calling `AddAssignment`:

```cpp
if (assignee.offset() < 0 || assignee.size() < 0) {
  return absl::OutOfRangeError(absl::StrCat(
      "BufferAssignment proto contains an assigned buffer with negative ",
      "offset or size: logical_buffer_id=", logical_buffer_id,
      " offset=", assignee.offset(), " size=", assignee.size()));
}
```

## Testing

Two new test cases in `buffer_assignment_test.cc`:
- `BufferAssignmentFromProtoTest.RejectsNegativeOffset`: confirms `offset=-1` bypasses `CHECK_LE` guards (proving the vulnerability) and documents that the fix must reject it before reaching `AddAssignment`
- `BufferAssignmentFromProtoTest.RejectsNegativeSize`: same for `size=-1`

---

*Disclosure: this contribution was authored with the aid of an AI coding assistant and reviewed before submission.*
Copybara import of the project:

--
6fab2ecd47988e30cfe195becfaecdb641479e8c by prasanna8585 <[email protected]>:

[XLA] Validate assigned buffer offset/size in BufferAssignment::FromProto

BufferAssignment::FromProto passes assignee.offset() and assignee.size()
from a deserialized BufferAllocationProto.Assigned proto directly to
BufferAllocation::AddAssignment without checking for negative values.

The CHECK_LE guards in AddAssignment are bypassed by negative int64 values:
  CHECK_LE(-1, 1024) = true  (for any real allocation)
  CHECK_LE(-1 + 4, 1024) = true

So a negative offset is stored in assigned_buffers_ and later used in LLVM
IR codegen (ir_emitter.cc) as:
  tempbuf_address_base + b()->getInt64(slice.offset())
With offset=-1 this is an out-of-bounds address.

This mirrors the fix applied to Slice::FromProto in PR #44653 (2840cd3),
which fixed the thunk deserialization path but missed this sibling path
in BufferAssignment::FromProto.

Fix: add an explicit negative check before calling AddAssignment,
returning absl::OutOfRangeError for negative offset or size values.

Add two regression tests confirming the bypass behavior and documenting
the required fix behavior.

Merging this change closes #46105

FUTURE_COPYBARA_INTEGRATE_REVIEW=openxla/xla#46105 from prasanna8585:fix/buffer-assignment-from-proto-negative-offset 6fab2ecd47988e30cfe195becfaecdb641479e8c
PiperOrigin-RevId: 952638612
copybara-service Bot pushed a commit that referenced this pull request Jul 27, 2026
…ment::FromProto

Imported from GitHub PR openxla/xla#46105

## Problem

`BufferAssignment::FromProto` passes `assignee.offset()` and `assignee.size()` from a deserialized `BufferAllocationProto.Assigned` proto directly to `BufferAllocation::AddAssignment` without checking for negative values.

The guards inside `AddAssignment` are:
```cpp
CHECK_LE(offset, size_)        // checks offset <= allocation.size()
CHECK_LE(offset + size, size_) // checks offset + size <= allocation.size()
```

These `CHECK_LE` guards are **bypassed by negative int64 values**: `-1 <= 1024` is true for any real allocation, so a negative offset passes both checks and gets stored in `assigned_buffers_`.

The stored negative offset is later used in LLVM IR codegen (`ir_emitter.cc`):
```cpp
tempbuf_address_base + b()->getInt64(slice.offset())
```
With `offset = -1`, this produces a pointer one byte before the allocation — an out-of-bounds address.

## Attack Surface

Reachable from `CpuAotLoader::LoadAotCompilationResult(serialized_aot_result)` where `serialized_aot_result` is a user-supplied serialized AOT executable. The proto fields `offset` and `size` are both `int64` in `hlo.proto`, so negative values are fully valid at the wire level.

## Relationship to PR #44653

PR #44653 (`2840cd3`) fixed `Slice::FromProto` with:
```cpp
if (proto.offset() < 0 || proto.size() < 0) {
  return absl::OutOfRangeError(...);
}
```

This PR applies the **same fix** to `BufferAssignment::FromProto` → `AddAssignment` path, which handles `Assigned` buffers in `BufferAllocationProto` — the sibling that the previous fix missed.

## Fix

Added a pre-validation check in `BufferAssignment::FromProto` before calling `AddAssignment`:

```cpp
if (assignee.offset() < 0 || assignee.size() < 0) {
  return absl::OutOfRangeError(absl::StrCat(
      "BufferAssignment proto contains an assigned buffer with negative ",
      "offset or size: logical_buffer_id=", logical_buffer_id,
      " offset=", assignee.offset(), " size=", assignee.size()));
}
```

## Testing

Two new test cases in `buffer_assignment_test.cc`:
- `BufferAssignmentFromProtoTest.RejectsNegativeOffset`: confirms `offset=-1` bypasses `CHECK_LE` guards (proving the vulnerability) and documents that the fix must reject it before reaching `AddAssignment`
- `BufferAssignmentFromProtoTest.RejectsNegativeSize`: same for `size=-1`

---

*Disclosure: this contribution was authored with the aid of an AI coding assistant and reviewed before submission.*
Copybara import of the project:

--
6fab2ecd47988e30cfe195becfaecdb641479e8c by prasanna8585 <[email protected]>:

[XLA] Validate assigned buffer offset/size in BufferAssignment::FromProto

BufferAssignment::FromProto passes assignee.offset() and assignee.size()
from a deserialized BufferAllocationProto.Assigned proto directly to
BufferAllocation::AddAssignment without checking for negative values.

The CHECK_LE guards in AddAssignment are bypassed by negative int64 values:
  CHECK_LE(-1, 1024) = true  (for any real allocation)
  CHECK_LE(-1 + 4, 1024) = true

So a negative offset is stored in assigned_buffers_ and later used in LLVM
IR codegen (ir_emitter.cc) as:
  tempbuf_address_base + b()->getInt64(slice.offset())
With offset=-1 this is an out-of-bounds address.

This mirrors the fix applied to Slice::FromProto in PR #44653 (2840cd3),
which fixed the thunk deserialization path but missed this sibling path
in BufferAssignment::FromProto.

Fix: add an explicit negative check before calling AddAssignment,
returning absl::OutOfRangeError for negative offset or size values.

Add two regression tests confirming the bypass behavior and documenting
the required fix behavior.

Merging this change closes #46105

FUTURE_COPYBARA_INTEGRATE_REVIEW=openxla/xla#46105 from prasanna8585:fix/buffer-assignment-from-proto-negative-offset 6fab2ecd47988e30cfe195becfaecdb641479e8c
PiperOrigin-RevId: 952638612
copybara-service Bot pushed a commit that referenced this pull request Jul 27, 2026
…:AddAssignment

Imported from GitHub PR openxla/xla#46105

## Problem

`BufferAssignment::FromProto` passes `assignee.offset()` and `assignee.size()` from a deserialized `BufferAllocationProto.Assigned` proto directly to `BufferAllocation::AddAssignment` without checking for negative values.

The guards inside `AddAssignment` are:
```cpp
CHECK_LE(offset, size_)        // checks offset <= allocation.size()
CHECK_LE(offset + size, size_) // checks offset + size <= allocation.size()
```

These `CHECK_LE` guards are **bypassed by negative int64 values**: `-1 <= 1024` is true for any real allocation, so a negative offset passes both checks and gets stored in `assigned_buffers_`.

The stored negative offset is later used in LLVM IR codegen (`ir_emitter.cc`):
```cpp
tempbuf_address_base + b()->getInt64(slice.offset())
```
With `offset = -1`, this produces a pointer one byte before the allocation — an out-of-bounds address.

## Attack Surface

Reachable from `CpuAotLoader::LoadAotCompilationResult(serialized_aot_result)` where `serialized_aot_result` is a user-supplied serialized AOT executable. The proto fields `offset` and `size` are both `int64` in `hlo.proto`, so negative values are fully valid at the wire level.

## Relationship to PR #44653

PR #44653 (`2840cd3`) fixed `Slice::FromProto` with:
```cpp
if (proto.offset() < 0 || proto.size() < 0) {
  return absl::OutOfRangeError(...);
}
```

This PR applies the **same fix** to `BufferAssignment::FromProto` → `AddAssignment` path, which handles `Assigned` buffers in `BufferAllocationProto` — the sibling that the previous fix missed.

## Fix

Added a pre-validation check in `BufferAssignment::FromProto` before calling `AddAssignment`:

```cpp
if (assignee.offset() < 0 || assignee.size() < 0) {
  return absl::OutOfRangeError(absl::StrCat(
      "BufferAssignment proto contains an assigned buffer with negative ",
      "offset or size: logical_buffer_id=", logical_buffer_id,
      " offset=", assignee.offset(), " size=", assignee.size()));
}
```

## Testing

Two new test cases in `buffer_assignment_test.cc`:
- `BufferAssignmentFromProtoTest.RejectsNegativeOffset`: confirms `offset=-1` bypasses `CHECK_LE` guards (proving the vulnerability) and documents that the fix must reject it before reaching `AddAssignment`
- `BufferAssignmentFromProtoTest.RejectsNegativeSize`: same for `size=-1`

---

*Disclosure: this contribution was authored with the aid of an AI coding assistant and reviewed before submission.*
Copybara import of the project:

--
6fab2ecd47988e30cfe195becfaecdb641479e8c by prasanna8585 <[email protected]>:

[XLA] Validate assigned buffer offset/size in BufferAssignment::FromProto

BufferAssignment::FromProto passes assignee.offset() and assignee.size()
from a deserialized BufferAllocationProto.Assigned proto directly to
BufferAllocation::AddAssignment without checking for negative values.

The CHECK_LE guards in AddAssignment are bypassed by negative int64 values:
  CHECK_LE(-1, 1024) = true  (for any real allocation)
  CHECK_LE(-1 + 4, 1024) = true

So a negative offset is stored in assigned_buffers_ and later used in LLVM
IR codegen (ir_emitter.cc) as:
  tempbuf_address_base + b()->getInt64(slice.offset())
With offset=-1 this is an out-of-bounds address.

This mirrors the fix applied to Slice::FromProto in PR #44653 (2840cd3),
which fixed the thunk deserialization path but missed this sibling path
in BufferAssignment::FromProto.

Fix: add an explicit negative check before calling AddAssignment,
returning absl::OutOfRangeError for negative offset or size values.

Add two regression tests confirming the bypass behavior and documenting
the required fix behavior.

--
5fdce18c4bdf2e1e53731611bc08938cf3669a05 by prasanna8585 <[email protected]>:

Address review: move fix from FromProto to BufferAllocation::AddAssignment

Per review feedback from @beckerhe: move the negative offset/size
validation from a precondition check in BufferAssignment::FromProto
into BufferAllocation::AddAssignment itself, converting the existing
CHECK_LE statements to TF_RET_CHECK. This protects every caller of
AddAssignment (there are ~9 call sites across buffer_assignment.cc),
not just the FromProto deserialization path, and returns an
absl::Status error instead of crashing the process when the
precondition is violated.

Also adds explicit offset >= 0 / size >= 0 checks: converting
CHECK_LE(offset, size_) to TF_RET_CHECK alone would not catch a
negative offset, since offset <= size_ is still true for any
negative offset and non-negative allocation size.

All 9 existing call sites already propagate the returned Status via
RETURN_IF_ERROR, so no call-site changes were needed beyond removing
the now-redundant check in FromProto.

Merging this change closes #46105

FUTURE_COPYBARA_INTEGRATE_REVIEW=openxla/xla#46105 from prasanna8585:fix/buffer-assignment-from-proto-negative-offset 5fdce18c4bdf2e1e53731611bc08938cf3669a05
PiperOrigin-RevId: 952638612
copybara-service Bot pushed a commit that referenced this pull request Jul 27, 2026
…:AddAssignment

Imported from GitHub PR openxla/xla#46105

## Problem

`BufferAssignment::FromProto` passes `assignee.offset()` and `assignee.size()` from a deserialized `BufferAllocationProto.Assigned` proto directly to `BufferAllocation::AddAssignment` without checking for negative values.

The guards inside `AddAssignment` are:
```cpp
CHECK_LE(offset, size_)        // checks offset <= allocation.size()
CHECK_LE(offset + size, size_) // checks offset + size <= allocation.size()
```

These `CHECK_LE` guards are **bypassed by negative int64 values**: `-1 <= 1024` is true for any real allocation, so a negative offset passes both checks and gets stored in `assigned_buffers_`.

The stored negative offset is later used in LLVM IR codegen (`ir_emitter.cc`):
```cpp
tempbuf_address_base + b()->getInt64(slice.offset())
```
With `offset = -1`, this produces a pointer one byte before the allocation — an out-of-bounds address.

## Attack Surface

Reachable from `CpuAotLoader::LoadAotCompilationResult(serialized_aot_result)` where `serialized_aot_result` is a user-supplied serialized AOT executable. The proto fields `offset` and `size` are both `int64` in `hlo.proto`, so negative values are fully valid at the wire level.

## Relationship to PR #44653

PR #44653 (`2840cd3`) fixed `Slice::FromProto` with:
```cpp
if (proto.offset() < 0 || proto.size() < 0) {
  return absl::OutOfRangeError(...);
}
```

This PR applies the **same fix** to `BufferAssignment::FromProto` → `AddAssignment` path, which handles `Assigned` buffers in `BufferAllocationProto` — the sibling that the previous fix missed.

## Fix

Added a pre-validation check in `BufferAssignment::FromProto` before calling `AddAssignment`:

```cpp
if (assignee.offset() < 0 || assignee.size() < 0) {
  return absl::OutOfRangeError(absl::StrCat(
      "BufferAssignment proto contains an assigned buffer with negative ",
      "offset or size: logical_buffer_id=", logical_buffer_id,
      " offset=", assignee.offset(), " size=", assignee.size()));
}
```

## Testing

Two new test cases in `buffer_assignment_test.cc`:
- `BufferAssignmentFromProtoTest.RejectsNegativeOffset`: confirms `offset=-1` bypasses `CHECK_LE` guards (proving the vulnerability) and documents that the fix must reject it before reaching `AddAssignment`
- `BufferAssignmentFromProtoTest.RejectsNegativeSize`: same for `size=-1`

---

*Disclosure: this contribution was authored with the aid of an AI coding assistant and reviewed before submission.*
Copybara import of the project:

--
6fab2ecd47988e30cfe195becfaecdb641479e8c by prasanna8585 <[email protected]>:

[XLA] Validate assigned buffer offset/size in BufferAssignment::FromProto

BufferAssignment::FromProto passes assignee.offset() and assignee.size()
from a deserialized BufferAllocationProto.Assigned proto directly to
BufferAllocation::AddAssignment without checking for negative values.

The CHECK_LE guards in AddAssignment are bypassed by negative int64 values:
  CHECK_LE(-1, 1024) = true  (for any real allocation)
  CHECK_LE(-1 + 4, 1024) = true

So a negative offset is stored in assigned_buffers_ and later used in LLVM
IR codegen (ir_emitter.cc) as:
  tempbuf_address_base + b()->getInt64(slice.offset())
With offset=-1 this is an out-of-bounds address.

This mirrors the fix applied to Slice::FromProto in PR #44653 (2840cd3),
which fixed the thunk deserialization path but missed this sibling path
in BufferAssignment::FromProto.

Fix: add an explicit negative check before calling AddAssignment,
returning absl::OutOfRangeError for negative offset or size values.

Add two regression tests confirming the bypass behavior and documenting
the required fix behavior.

--
5fdce18c4bdf2e1e53731611bc08938cf3669a05 by prasanna8585 <[email protected]>:

Address review: move fix from FromProto to BufferAllocation::AddAssignment

Per review feedback from @beckerhe: move the negative offset/size
validation from a precondition check in BufferAssignment::FromProto
into BufferAllocation::AddAssignment itself, converting the existing
CHECK_LE statements to TF_RET_CHECK. This protects every caller of
AddAssignment (there are ~9 call sites across buffer_assignment.cc),
not just the FromProto deserialization path, and returns an
absl::Status error instead of crashing the process when the
precondition is violated.

Also adds explicit offset >= 0 / size >= 0 checks: converting
CHECK_LE(offset, size_) to TF_RET_CHECK alone would not catch a
negative offset, since offset <= size_ is still true for any
negative offset and non-negative allocation size.

All 9 existing call sites already propagate the returned Status via
RETURN_IF_ERROR, so no call-site changes were needed beyond removing
the now-redundant check in FromProto.

Merging this change closes #46105

FUTURE_COPYBARA_INTEGRATE_REVIEW=openxla/xla#46105 from prasanna8585:fix/buffer-assignment-from-proto-negative-offset 5fdce18c4bdf2e1e53731611bc08938cf3669a05
PiperOrigin-RevId: 952638612
copybara-service Bot pushed a commit that referenced this pull request Jul 27, 2026
…:AddAssignment

Imported from GitHub PR openxla/xla#46105

## Problem

`BufferAssignment::FromProto` passes `assignee.offset()` and `assignee.size()` from a deserialized `BufferAllocationProto.Assigned` proto directly to `BufferAllocation::AddAssignment` without checking for negative values.

The guards inside `AddAssignment` are:
```cpp
CHECK_LE(offset, size_)        // checks offset <= allocation.size()
CHECK_LE(offset + size, size_) // checks offset + size <= allocation.size()
```

These `CHECK_LE` guards are **bypassed by negative int64 values**: `-1 <= 1024` is true for any real allocation, so a negative offset passes both checks and gets stored in `assigned_buffers_`.

The stored negative offset is later used in LLVM IR codegen (`ir_emitter.cc`):
```cpp
tempbuf_address_base + b()->getInt64(slice.offset())
```
With `offset = -1`, this produces a pointer one byte before the allocation — an out-of-bounds address.

## Attack Surface

Reachable from `CpuAotLoader::LoadAotCompilationResult(serialized_aot_result)` where `serialized_aot_result` is a user-supplied serialized AOT executable. The proto fields `offset` and `size` are both `int64` in `hlo.proto`, so negative values are fully valid at the wire level.

## Relationship to PR #44653

PR #44653 (`2840cd3`) fixed `Slice::FromProto` with:
```cpp
if (proto.offset() < 0 || proto.size() < 0) {
  return absl::OutOfRangeError(...);
}
```

This PR applies the **same fix** to `BufferAssignment::FromProto` → `AddAssignment` path, which handles `Assigned` buffers in `BufferAllocationProto` — the sibling that the previous fix missed.

## Fix

Added a pre-validation check in `BufferAssignment::FromProto` before calling `AddAssignment`:

```cpp
if (assignee.offset() < 0 || assignee.size() < 0) {
  return absl::OutOfRangeError(absl::StrCat(
      "BufferAssignment proto contains an assigned buffer with negative ",
      "offset or size: logical_buffer_id=", logical_buffer_id,
      " offset=", assignee.offset(), " size=", assignee.size()));
}
```

## Testing

Two new test cases in `buffer_assignment_test.cc`:
- `BufferAssignmentFromProtoTest.RejectsNegativeOffset`: confirms `offset=-1` bypasses `CHECK_LE` guards (proving the vulnerability) and documents that the fix must reject it before reaching `AddAssignment`
- `BufferAssignmentFromProtoTest.RejectsNegativeSize`: same for `size=-1`

---

*Disclosure: this contribution was authored with the aid of an AI coding assistant and reviewed before submission.*
Copybara import of the project:

--
6fab2ecd47988e30cfe195becfaecdb641479e8c by prasanna8585 <[email protected]>:

[XLA] Validate assigned buffer offset/size in BufferAssignment::FromProto

BufferAssignment::FromProto passes assignee.offset() and assignee.size()
from a deserialized BufferAllocationProto.Assigned proto directly to
BufferAllocation::AddAssignment without checking for negative values.

The CHECK_LE guards in AddAssignment are bypassed by negative int64 values:
  CHECK_LE(-1, 1024) = true  (for any real allocation)
  CHECK_LE(-1 + 4, 1024) = true

So a negative offset is stored in assigned_buffers_ and later used in LLVM
IR codegen (ir_emitter.cc) as:
  tempbuf_address_base + b()->getInt64(slice.offset())
With offset=-1 this is an out-of-bounds address.

This mirrors the fix applied to Slice::FromProto in PR #44653 (2840cd3),
which fixed the thunk deserialization path but missed this sibling path
in BufferAssignment::FromProto.

Fix: add an explicit negative check before calling AddAssignment,
returning absl::OutOfRangeError for negative offset or size values.

Add two regression tests confirming the bypass behavior and documenting
the required fix behavior.

--
5fdce18c4bdf2e1e53731611bc08938cf3669a05 by prasanna8585 <[email protected]>:

Address review: move fix from FromProto to BufferAllocation::AddAssignment

Per review feedback from @beckerhe: move the negative offset/size
validation from a precondition check in BufferAssignment::FromProto
into BufferAllocation::AddAssignment itself, converting the existing
CHECK_LE statements to TF_RET_CHECK. This protects every caller of
AddAssignment (there are ~9 call sites across buffer_assignment.cc),
not just the FromProto deserialization path, and returns an
absl::Status error instead of crashing the process when the
precondition is violated.

Also adds explicit offset >= 0 / size >= 0 checks: converting
CHECK_LE(offset, size_) to TF_RET_CHECK alone would not catch a
negative offset, since offset <= size_ is still true for any
negative offset and non-negative allocation size.

All 9 existing call sites already propagate the returned Status via
RETURN_IF_ERROR, so no call-site changes were needed beyond removing
the now-redundant check in FromProto.

Merging this change closes #46105

FUTURE_COPYBARA_INTEGRATE_REVIEW=openxla/xla#46105 from prasanna8585:fix/buffer-assignment-from-proto-negative-offset 5fdce18c4bdf2e1e53731611bc08938cf3669a05
PiperOrigin-RevId: 952638612
copybara-service Bot pushed a commit that referenced this pull request Jul 28, 2026
…:AddAssignment

Imported from GitHub PR openxla/xla#46105

## Problem

`BufferAssignment::FromProto` passes `assignee.offset()` and `assignee.size()` from a deserialized `BufferAllocationProto.Assigned` proto directly to `BufferAllocation::AddAssignment` without checking for negative values.

The guards inside `AddAssignment` are:
```cpp
CHECK_LE(offset, size_)        // checks offset <= allocation.size()
CHECK_LE(offset + size, size_) // checks offset + size <= allocation.size()
```

These `CHECK_LE` guards are **bypassed by negative int64 values**: `-1 <= 1024` is true for any real allocation, so a negative offset passes both checks and gets stored in `assigned_buffers_`.

The stored negative offset is later used in LLVM IR codegen (`ir_emitter.cc`):
```cpp
tempbuf_address_base + b()->getInt64(slice.offset())
```
With `offset = -1`, this produces a pointer one byte before the allocation — an out-of-bounds address.

## Attack Surface

Reachable from `CpuAotLoader::LoadAotCompilationResult(serialized_aot_result)` where `serialized_aot_result` is a user-supplied serialized AOT executable. The proto fields `offset` and `size` are both `int64` in `hlo.proto`, so negative values are fully valid at the wire level.

## Relationship to PR #44653

PR #44653 (`2840cd3`) fixed `Slice::FromProto` with:
```cpp
if (proto.offset() < 0 || proto.size() < 0) {
  return absl::OutOfRangeError(...);
}
```

This PR applies the **same fix** to `BufferAssignment::FromProto` → `AddAssignment` path, which handles `Assigned` buffers in `BufferAllocationProto` — the sibling that the previous fix missed.

## Fix

Added a pre-validation check in `BufferAssignment::FromProto` before calling `AddAssignment`:

```cpp
if (assignee.offset() < 0 || assignee.size() < 0) {
  return absl::OutOfRangeError(absl::StrCat(
      "BufferAssignment proto contains an assigned buffer with negative ",
      "offset or size: logical_buffer_id=", logical_buffer_id,
      " offset=", assignee.offset(), " size=", assignee.size()));
}
```

## Testing

Two new test cases in `buffer_assignment_test.cc`:
- `BufferAssignmentFromProtoTest.RejectsNegativeOffset`: confirms `offset=-1` bypasses `CHECK_LE` guards (proving the vulnerability) and documents that the fix must reject it before reaching `AddAssignment`
- `BufferAssignmentFromProtoTest.RejectsNegativeSize`: same for `size=-1`

---

*Disclosure: this contribution was authored with the aid of an AI coding assistant and reviewed before submission.*
Copybara import of the project:

--
6fab2ecd47988e30cfe195becfaecdb641479e8c by prasanna8585 <[email protected]>:

[XLA] Validate assigned buffer offset/size in BufferAssignment::FromProto

BufferAssignment::FromProto passes assignee.offset() and assignee.size()
from a deserialized BufferAllocationProto.Assigned proto directly to
BufferAllocation::AddAssignment without checking for negative values.

The CHECK_LE guards in AddAssignment are bypassed by negative int64 values:
  CHECK_LE(-1, 1024) = true  (for any real allocation)
  CHECK_LE(-1 + 4, 1024) = true

So a negative offset is stored in assigned_buffers_ and later used in LLVM
IR codegen (ir_emitter.cc) as:
  tempbuf_address_base + b()->getInt64(slice.offset())
With offset=-1 this is an out-of-bounds address.

This mirrors the fix applied to Slice::FromProto in PR #44653 (2840cd3),
which fixed the thunk deserialization path but missed this sibling path
in BufferAssignment::FromProto.

Fix: add an explicit negative check before calling AddAssignment,
returning absl::OutOfRangeError for negative offset or size values.

Add two regression tests confirming the bypass behavior and documenting
the required fix behavior.

--
5fdce18c4bdf2e1e53731611bc08938cf3669a05 by prasanna8585 <[email protected]>:

Address review: move fix from FromProto to BufferAllocation::AddAssignment

Per review feedback from @beckerhe: move the negative offset/size
validation from a precondition check in BufferAssignment::FromProto
into BufferAllocation::AddAssignment itself, converting the existing
CHECK_LE statements to TF_RET_CHECK. This protects every caller of
AddAssignment (there are ~9 call sites across buffer_assignment.cc),
not just the FromProto deserialization path, and returns an
absl::Status error instead of crashing the process when the
precondition is violated.

Also adds explicit offset >= 0 / size >= 0 checks: converting
CHECK_LE(offset, size_) to TF_RET_CHECK alone would not catch a
negative offset, since offset <= size_ is still true for any
negative offset and non-negative allocation size.

All 9 existing call sites already propagate the returned Status via
RETURN_IF_ERROR, so no call-site changes were needed beyond removing
the now-redundant check in FromProto.

Merging this change closes #46105

FUTURE_COPYBARA_INTEGRATE_REVIEW=openxla/xla#46105 from prasanna8585:fix/buffer-assignment-from-proto-negative-offset 5fdce18c4bdf2e1e53731611bc08938cf3669a05
PiperOrigin-RevId: 952638612
copybara-service Bot pushed a commit that referenced this pull request Jul 28, 2026
…:AddAssignment

Imported from GitHub PR openxla/xla#46105

## Problem

`BufferAssignment::FromProto` passes `assignee.offset()` and `assignee.size()` from a deserialized `BufferAllocationProto.Assigned` proto directly to `BufferAllocation::AddAssignment` without checking for negative values.

The guards inside `AddAssignment` are:
```cpp
CHECK_LE(offset, size_)        // checks offset <= allocation.size()
CHECK_LE(offset + size, size_) // checks offset + size <= allocation.size()
```

These `CHECK_LE` guards are **bypassed by negative int64 values**: `-1 <= 1024` is true for any real allocation, so a negative offset passes both checks and gets stored in `assigned_buffers_`.

The stored negative offset is later used in LLVM IR codegen (`ir_emitter.cc`):
```cpp
tempbuf_address_base + b()->getInt64(slice.offset())
```
With `offset = -1`, this produces a pointer one byte before the allocation — an out-of-bounds address.

## Attack Surface

Reachable from `CpuAotLoader::LoadAotCompilationResult(serialized_aot_result)` where `serialized_aot_result` is a user-supplied serialized AOT executable. The proto fields `offset` and `size` are both `int64` in `hlo.proto`, so negative values are fully valid at the wire level.

## Relationship to PR #44653

PR #44653 (`2840cd3`) fixed `Slice::FromProto` with:
```cpp
if (proto.offset() < 0 || proto.size() < 0) {
  return absl::OutOfRangeError(...);
}
```

This PR applies the **same fix** to `BufferAssignment::FromProto` → `AddAssignment` path, which handles `Assigned` buffers in `BufferAllocationProto` — the sibling that the previous fix missed.

## Fix

Added a pre-validation check in `BufferAssignment::FromProto` before calling `AddAssignment`:

```cpp
if (assignee.offset() < 0 || assignee.size() < 0) {
  return absl::OutOfRangeError(absl::StrCat(
      "BufferAssignment proto contains an assigned buffer with negative ",
      "offset or size: logical_buffer_id=", logical_buffer_id,
      " offset=", assignee.offset(), " size=", assignee.size()));
}
```

## Testing

Two new test cases in `buffer_assignment_test.cc`:
- `BufferAssignmentFromProtoTest.RejectsNegativeOffset`: confirms `offset=-1` bypasses `CHECK_LE` guards (proving the vulnerability) and documents that the fix must reject it before reaching `AddAssignment`
- `BufferAssignmentFromProtoTest.RejectsNegativeSize`: same for `size=-1`

---

*Disclosure: this contribution was authored with the aid of an AI coding assistant and reviewed before submission.*
Copybara import of the project:

--
6fab2ecd47988e30cfe195becfaecdb641479e8c by prasanna8585 <[email protected]>:

[XLA] Validate assigned buffer offset/size in BufferAssignment::FromProto

BufferAssignment::FromProto passes assignee.offset() and assignee.size()
from a deserialized BufferAllocationProto.Assigned proto directly to
BufferAllocation::AddAssignment without checking for negative values.

The CHECK_LE guards in AddAssignment are bypassed by negative int64 values:
  CHECK_LE(-1, 1024) = true  (for any real allocation)
  CHECK_LE(-1 + 4, 1024) = true

So a negative offset is stored in assigned_buffers_ and later used in LLVM
IR codegen (ir_emitter.cc) as:
  tempbuf_address_base + b()->getInt64(slice.offset())
With offset=-1 this is an out-of-bounds address.

This mirrors the fix applied to Slice::FromProto in PR #44653 (2840cd3),
which fixed the thunk deserialization path but missed this sibling path
in BufferAssignment::FromProto.

Fix: add an explicit negative check before calling AddAssignment,
returning absl::OutOfRangeError for negative offset or size values.

Add two regression tests confirming the bypass behavior and documenting
the required fix behavior.

--
5fdce18c4bdf2e1e53731611bc08938cf3669a05 by prasanna8585 <[email protected]>:

Address review: move fix from FromProto to BufferAllocation::AddAssignment

Per review feedback from @beckerhe: move the negative offset/size
validation from a precondition check in BufferAssignment::FromProto
into BufferAllocation::AddAssignment itself, converting the existing
CHECK_LE statements to TF_RET_CHECK. This protects every caller of
AddAssignment (there are ~9 call sites across buffer_assignment.cc),
not just the FromProto deserialization path, and returns an
absl::Status error instead of crashing the process when the
precondition is violated.

Also adds explicit offset >= 0 / size >= 0 checks: converting
CHECK_LE(offset, size_) to TF_RET_CHECK alone would not catch a
negative offset, since offset <= size_ is still true for any
negative offset and non-negative allocation size.

All 9 existing call sites already propagate the returned Status via
RETURN_IF_ERROR, so no call-site changes were needed beyond removing
the now-redundant check in FromProto.

Merging this change closes #46105

FUTURE_COPYBARA_INTEGRATE_REVIEW=openxla/xla#46105 from prasanna8585:fix/buffer-assignment-from-proto-negative-offset 5fdce18c4bdf2e1e53731611bc08938cf3669a05
PiperOrigin-RevId: 952638612
copybara-service Bot pushed a commit that referenced this pull request Jul 28, 2026
…:AddAssignment

Imported from GitHub PR openxla/xla#46105

## Problem

`BufferAssignment::FromProto` passes `assignee.offset()` and `assignee.size()` from a deserialized `BufferAllocationProto.Assigned` proto directly to `BufferAllocation::AddAssignment` without checking for negative values.

The guards inside `AddAssignment` are:
```cpp
CHECK_LE(offset, size_)        // checks offset <= allocation.size()
CHECK_LE(offset + size, size_) // checks offset + size <= allocation.size()
```

These `CHECK_LE` guards are **bypassed by negative int64 values**: `-1 <= 1024` is true for any real allocation, so a negative offset passes both checks and gets stored in `assigned_buffers_`.

The stored negative offset is later used in LLVM IR codegen (`ir_emitter.cc`):
```cpp
tempbuf_address_base + b()->getInt64(slice.offset())
```
With `offset = -1`, this produces a pointer one byte before the allocation — an out-of-bounds address.

## Attack Surface

Reachable from `CpuAotLoader::LoadAotCompilationResult(serialized_aot_result)` where `serialized_aot_result` is a user-supplied serialized AOT executable. The proto fields `offset` and `size` are both `int64` in `hlo.proto`, so negative values are fully valid at the wire level.

## Relationship to PR #44653

PR #44653 (`2840cd3`) fixed `Slice::FromProto` with:
```cpp
if (proto.offset() < 0 || proto.size() < 0) {
  return absl::OutOfRangeError(...);
}
```

This PR applies the **same fix** to `BufferAssignment::FromProto` → `AddAssignment` path, which handles `Assigned` buffers in `BufferAllocationProto` — the sibling that the previous fix missed.

## Fix

Added a pre-validation check in `BufferAssignment::FromProto` before calling `AddAssignment`:

```cpp
if (assignee.offset() < 0 || assignee.size() < 0) {
  return absl::OutOfRangeError(absl::StrCat(
      "BufferAssignment proto contains an assigned buffer with negative ",
      "offset or size: logical_buffer_id=", logical_buffer_id,
      " offset=", assignee.offset(), " size=", assignee.size()));
}
```

## Testing

Two new test cases in `buffer_assignment_test.cc`:
- `BufferAssignmentFromProtoTest.RejectsNegativeOffset`: confirms `offset=-1` bypasses `CHECK_LE` guards (proving the vulnerability) and documents that the fix must reject it before reaching `AddAssignment`
- `BufferAssignmentFromProtoTest.RejectsNegativeSize`: same for `size=-1`

---

*Disclosure: this contribution was authored with the aid of an AI coding assistant and reviewed before submission.*
Copybara import of the project:

--
6fab2ecd47988e30cfe195becfaecdb641479e8c by prasanna8585 <[email protected]>:

[XLA] Validate assigned buffer offset/size in BufferAssignment::FromProto

BufferAssignment::FromProto passes assignee.offset() and assignee.size()
from a deserialized BufferAllocationProto.Assigned proto directly to
BufferAllocation::AddAssignment without checking for negative values.

The CHECK_LE guards in AddAssignment are bypassed by negative int64 values:
  CHECK_LE(-1, 1024) = true  (for any real allocation)
  CHECK_LE(-1 + 4, 1024) = true

So a negative offset is stored in assigned_buffers_ and later used in LLVM
IR codegen (ir_emitter.cc) as:
  tempbuf_address_base + b()->getInt64(slice.offset())
With offset=-1 this is an out-of-bounds address.

This mirrors the fix applied to Slice::FromProto in PR #44653 (2840cd3),
which fixed the thunk deserialization path but missed this sibling path
in BufferAssignment::FromProto.

Fix: add an explicit negative check before calling AddAssignment,
returning absl::OutOfRangeError for negative offset or size values.

Add two regression tests confirming the bypass behavior and documenting
the required fix behavior.

--
5fdce18c4bdf2e1e53731611bc08938cf3669a05 by prasanna8585 <[email protected]>:

Address review: move fix from FromProto to BufferAllocation::AddAssignment

Per review feedback from @beckerhe: move the negative offset/size
validation from a precondition check in BufferAssignment::FromProto
into BufferAllocation::AddAssignment itself, converting the existing
CHECK_LE statements to TF_RET_CHECK. This protects every caller of
AddAssignment (there are ~9 call sites across buffer_assignment.cc),
not just the FromProto deserialization path, and returns an
absl::Status error instead of crashing the process when the
precondition is violated.

Also adds explicit offset >= 0 / size >= 0 checks: converting
CHECK_LE(offset, size_) to TF_RET_CHECK alone would not catch a
negative offset, since offset <= size_ is still true for any
negative offset and non-negative allocation size.

All 9 existing call sites already propagate the returned Status via
RETURN_IF_ERROR, so no call-site changes were needed beyond removing
the now-redundant check in FromProto.

Merging this change closes #46105

PiperOrigin-RevId: 955212759
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cla: yes comp:keras Keras related issues ready to pull PR ready for merge process size:XS CL Change Size: Extra Small

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants