spanification: automatically spanify remoting/protocol/pseudo_tcp.cc etc. [chromium/src : main]

0 views
Skip to first unread message

Daniel Angulo (Gerrit)

unread,
Jan 28, 2026, 2:44:10 PMJan 28
to Stephen Nusko, Arthur Sonzogni, AyeAye, Chromium LUCI CQ, chromotin...@chromium.org
Attention needed from Arthur Sonzogni and Stephen Nusko

Daniel Angulo voted Commit-Queue+1

Commit-Queue+1
Open in Gerrit

Related details

Attention is currently required from:
  • Arthur Sonzogni
  • Stephen Nusko
Submit Requirements:
  • requirement satisfiedCode-Coverage
  • requirement is not satisfiedCode-Owners
  • requirement is not satisfiedCode-Review
  • requirement is not satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: chromium/src
Gerrit-Branch: main
Gerrit-Change-Id: Id1a0ff3462edd3d7fa119beff620570f1893a0d8
Gerrit-Change-Number: 7526157
Gerrit-PatchSet: 2
Gerrit-Owner: Daniel Angulo <angd...@google.com>
Gerrit-Reviewer: Arthur Sonzogni <arthurs...@google.com>
Gerrit-Reviewer: Daniel Angulo <angd...@google.com>
Gerrit-Reviewer: Stephen Nusko <nus...@chromium.org>
Gerrit-Attention: Stephen Nusko <nus...@chromium.org>
Gerrit-Attention: Arthur Sonzogni <arthurs...@google.com>
Gerrit-Comment-Date: Wed, 28 Jan 2026 19:44:00 +0000
Gerrit-HasComments: No
Gerrit-Has-Labels: Yes
satisfied_requirement
unsatisfied_requirement
open
diffy

Stephen Nusko (Gerrit)

unread,
Jan 28, 2026, 11:50:21 PMJan 28
to Daniel Angulo, Arthur Sonzogni, AyeAye, Chromium LUCI CQ, chromotin...@chromium.org
Attention needed from Arthur Sonzogni and Daniel Angulo

Stephen Nusko added 15 comments

File remoting/protocol/pseudo_tcp.h
Line 225, Patchset 2 (Latest): std::unique_ptr<char[]> buffer_ GUARDED_BY(lock_);
Stephen Nusko . unresolved

While we are here switch this to a base::HeapArray? and remove `buffer_length_`? (still need data_length_ most likely).

File remoting/protocol/pseudo_tcp.cc
Line 87, Patchset 2 (Latest): auto bytes = base::U32ToBigEndian(val);
Stephen Nusko . unresolved

Because this is network code might be best to do

`base::as_bytes(base::HostToNet32(val));`

Thoughts? Here and below?

I agree that new is BigEndian so that is fine, but they have a nice helper function and it probably makes more sense to keep it consistent?

Line 137, Patchset 2 (Latest): base::as_writable_bytes(UNSAFE_BUFFERS(base::span(str, len)))
Stephen Nusko . unresolved

We can't claim UNSAFE_BUFFERS here, what SAFETY message would you write?

We have 3 options
1) Make this function take std::string_view
2) Make this function UNSAFE_BUFFER_USAGE and force all callers to add UNSAFE_TODO or UNSAFE_BUFFERS
3) Mark this as UNSAFE_TODO for now until someone can do 1 or 2.

Line 143, Patchset 2 (Latest): const uint8_t* Data() const { return data_.subspan(pos_).data(); }
Stephen Nusko . unresolved

`&data_[pos_]`

is better I think?

Line 434, Patchset 2 (Latest): // SAFETY: `buffer` is a raw C-style array of size `len`, so we can safely
// reinterpret the pointer as a span of bytes.
Stephen Nusko . unresolved

The safety concern isn't from the reinterpret it is from no knowing if the length is correct. Same as above we can't use UNSAFE_BUFFERS here.

Line 589, Patchset 2 (Latest): std::unique_ptr<uint8_t[]> buffer(new uint8_t[MAX_PACKET]);
Stephen Nusko . unresolved

Switch this to a HeapArray then you can get a span directly.

Line 594, Patchset 2 (Latest): buffer_span.first<4u>().copy_from(base::U32ToBigEndian(m_conv));
buffer_span.subspan(4u).first<4u>().copy_from(base::U32ToBigEndian(seq));
buffer_span.subspan(8u).first<4u>().copy_from(
base::U32ToBigEndian(m_rcv_nxt));
buffer_span[12] = 0;
buffer_span[13] = flags;
buffer_span.subspan(14u).first<2u>().copy_from(
base::U16ToBigEndian(static_cast<uint16_t>(m_rcv_wnd >> m_rwnd_scale)));

// Timestamp computations
buffer_span.subspan(16u).first<4u>().copy_from(base::U32ToBigEndian(now));
buffer_span.subspan(20u).first<4u>().copy_from(
base::U32ToBigEndian(m_ts_recent));
Stephen Nusko . unresolved

This looks like a SpanWriter?

Line 650, Patchset 2 (Latest): seg.conv = base::U32FromBigEndian(buffer.first<4u>());
seg.seq = base::U32FromBigEndian(buffer.subspan(4u).first<4u>());
seg.ack = base::U32FromBigEndian(buffer.subspan(8u).first<4u>());
seg.flags = buffer[13];
seg.wnd = base::U16FromBigEndian(buffer.subspan(14u).first<2u>());
seg.tsval = base::U32FromBigEndian(buffer.subspan(16u).first<4u>());
seg.tsecr = base::U32FromBigEndian(buffer.subspan(20u).first<4u>());
Stephen Nusko . unresolved

This looks like a spanReader?

Line 920, Patchset 2 (Latest): } else if (seg.data.size() != 0) {
Stephen Nusko . unresolved

nit: !seq.data.empty()

Line 943, Patchset 2 (Latest): seg.data = seg.data.first(seg.data.size() - nAdjust);
Stephen Nusko . unresolved

I think you are double moving the buffer here?

```
seg.data += nAdjust;
seg.len -= nAdjust;
```

The old code moved the buffer and then decreased the length by the same amount (to keep them in sync).

Your new code moves the buffer forward by nAdjust and then takes a further nAdjust off in addition (this is incorrect).

Delete the seq.data.first line?

Line 992, Patchset 2 (Latest): if (!m_rbuf.WriteOffset(seg.data.data(), seg.data.size(), nOffset,
Stephen Nusko . unresolved

Can we update WriteOffset?

Line 1414, Patchset 2 (Latest):bool PseudoTcp::LockedFifoBuffer::WriteOffset(const void* buffer,
size_t bytes,
Stephen Nusko . unresolved

It looks like we call this function with a span could we update this one?

Line 1425, Patchset 2 (Latest):bool PseudoTcp::LockedFifoBuffer::Read(void* buffer,
size_t bytes,
Stephen Nusko . unresolved

Can we check all of these?

Line 1498, Patchset 2 (Latest): dest(reinterpret_cast<char*>(buffer.data()), buffer.size()));
Stephen Nusko . unresolved

base::as_writable_chars(buffer) should work no?

Line 1499, Patchset 2 (Latest): base::span<const char> UNSAFE_BUFFERS(
src(&buffer_[read_position], tail_copy));
dest.first(tail_copy).copy_from(src);
base::span<const char> UNSAFE_BUFFERS(src2(&buffer_[0], copy - tail_copy));
Stephen Nusko . unresolved

base::as_chars?

Open in Gerrit

Related details

Attention is currently required from:
  • Arthur Sonzogni
  • Daniel Angulo
Submit Requirements:
    • requirement satisfiedCode-Coverage
    • requirement is not satisfiedCode-Owners
    • requirement is not satisfiedCode-Review
    • requirement is not satisfiedNo-Unresolved-Comments
    • requirement is not satisfiedReview-Enforcement
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: comment
    Gerrit-Project: chromium/src
    Gerrit-Branch: main
    Gerrit-Change-Id: Id1a0ff3462edd3d7fa119beff620570f1893a0d8
    Gerrit-Change-Number: 7526157
    Gerrit-PatchSet: 2
    Gerrit-Owner: Daniel Angulo <angd...@google.com>
    Gerrit-Reviewer: Arthur Sonzogni <arthurs...@google.com>
    Gerrit-Reviewer: Daniel Angulo <angd...@google.com>
    Gerrit-Reviewer: Stephen Nusko <nus...@chromium.org>
    Gerrit-Attention: Daniel Angulo <angd...@google.com>
    Gerrit-Attention: Arthur Sonzogni <arthurs...@google.com>
    Gerrit-Comment-Date: Thu, 29 Jan 2026 04:50:00 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    Daniel Angulo (Gerrit)

    unread,
    Jan 29, 2026, 3:03:10 PMJan 29
    to Arthur Sonzogni, Stephen Nusko, AyeAye, Chromium LUCI CQ, chromotin...@chromium.org
    Attention needed from Arthur Sonzogni and Stephen Nusko

    Daniel Angulo added 15 comments

    File remoting/protocol/pseudo_tcp.h
    Line 225, Patchset 2: std::unique_ptr<char[]> buffer_ GUARDED_BY(lock_);
    Stephen Nusko . resolved

    While we are here switch this to a base::HeapArray? and remove `buffer_length_`? (still need data_length_ most likely).

    Daniel Angulo

    Done

    File remoting/protocol/pseudo_tcp.cc
    Line 87, Patchset 2: auto bytes = base::U32ToBigEndian(val);
    Stephen Nusko . resolved

    Because this is network code might be best to do

    `base::as_bytes(base::HostToNet32(val));`

    Thoughts? Here and below?

    I agree that new is BigEndian so that is fine, but they have a nice helper function and it probably makes more sense to keep it consistent?

    Daniel Angulo

    Done

    Line 137, Patchset 2: base::as_writable_bytes(UNSAFE_BUFFERS(base::span(str, len)))
    Stephen Nusko . unresolved

    We can't claim UNSAFE_BUFFERS here, what SAFETY message would you write?

    We have 3 options
    1) Make this function take std::string_view
    2) Make this function UNSAFE_BUFFER_USAGE and force all callers to add UNSAFE_TODO or UNSAFE_BUFFERS
    3) Mark this as UNSAFE_TODO for now until someone can do 1 or 2.

    Daniel Angulo

    I was thinking that string_view can't be used because it needs to write data on it, but making this function take a span<char> would work instead. However this function is not used anywhare, should I stray it?

    Line 143, Patchset 2: const uint8_t* Data() const { return data_.subspan(pos_).data(); }
    Stephen Nusko . resolved

    `&data_[pos_]`

    is better I think?

    Daniel Angulo

    Done

    Line 434, Patchset 2: // SAFETY: `buffer` is a raw C-style array of size `len`, so we can safely

    // reinterpret the pointer as a span of bytes.
    Stephen Nusko . resolved

    The safety concern isn't from the reinterpret it is from no knowing if the length is correct. Same as above we can't use UNSAFE_BUFFERS here.

    Daniel Angulo

    Done

    Line 589, Patchset 2: std::unique_ptr<uint8_t[]> buffer(new uint8_t[MAX_PACKET]);
    Stephen Nusko . resolved

    Switch this to a HeapArray then you can get a span directly.

    Daniel Angulo

    Done

    Line 594, Patchset 2: buffer_span.first<4u>().copy_from(base::U32ToBigEndian(m_conv));

    buffer_span.subspan(4u).first<4u>().copy_from(base::U32ToBigEndian(seq));
    buffer_span.subspan(8u).first<4u>().copy_from(
    base::U32ToBigEndian(m_rcv_nxt));
    buffer_span[12] = 0;
    buffer_span[13] = flags;
    buffer_span.subspan(14u).first<2u>().copy_from(
    base::U16ToBigEndian(static_cast<uint16_t>(m_rcv_wnd >> m_rwnd_scale)));

    // Timestamp computations
    buffer_span.subspan(16u).first<4u>().copy_from(base::U32ToBigEndian(now));
    buffer_span.subspan(20u).first<4u>().copy_from(
    base::U32ToBigEndian(m_ts_recent));
    Stephen Nusko . resolved

    This looks like a SpanWriter?

    Daniel Angulo

    Done

    Line 650, Patchset 2: seg.conv = base::U32FromBigEndian(buffer.first<4u>());

    seg.seq = base::U32FromBigEndian(buffer.subspan(4u).first<4u>());
    seg.ack = base::U32FromBigEndian(buffer.subspan(8u).first<4u>());
    seg.flags = buffer[13];
    seg.wnd = base::U16FromBigEndian(buffer.subspan(14u).first<2u>());
    seg.tsval = base::U32FromBigEndian(buffer.subspan(16u).first<4u>());
    seg.tsecr = base::U32FromBigEndian(buffer.subspan(20u).first<4u>());
    Stephen Nusko . resolved

    This looks like a spanReader?

    Daniel Angulo

    Done

    Line 920, Patchset 2: } else if (seg.data.size() != 0) {
    Stephen Nusko . resolved

    nit: !seq.data.empty()

    Daniel Angulo

    Done

    Line 943, Patchset 2: seg.data = seg.data.first(seg.data.size() - nAdjust);
    Stephen Nusko . resolved

    I think you are double moving the buffer here?

    ```
    seg.data += nAdjust;
    seg.len -= nAdjust;
    ```

    The old code moved the buffer and then decreased the length by the same amount (to keep them in sync).

    Your new code moves the buffer forward by nAdjust and then takes a further nAdjust off in addition (this is incorrect).

    Delete the seq.data.first line?

    Daniel Angulo

    Done

    Line 992, Patchset 2: if (!m_rbuf.WriteOffset(seg.data.data(), seg.data.size(), nOffset,
    Stephen Nusko . resolved

    Can we update WriteOffset?

    Daniel Angulo

    Done

    Line 1414, Patchset 2:bool PseudoTcp::LockedFifoBuffer::WriteOffset(const void* buffer,
    size_t bytes,
    Stephen Nusko . resolved

    It looks like we call this function with a span could we update this one?

    Daniel Angulo

    Done

    Line 1425, Patchset 2:bool PseudoTcp::LockedFifoBuffer::Read(void* buffer,
    size_t bytes,
    Stephen Nusko . resolved

    Can we check all of these?

    Daniel Angulo

    Done

    Line 1498, Patchset 2: dest(reinterpret_cast<char*>(buffer.data()), buffer.size()));
    Stephen Nusko . resolved

    base::as_writable_chars(buffer) should work no?

    Daniel Angulo

    Done

    Line 1499, Patchset 2: base::span<const char> UNSAFE_BUFFERS(

    src(&buffer_[read_position], tail_copy));
    dest.first(tail_copy).copy_from(src);
    base::span<const char> UNSAFE_BUFFERS(src2(&buffer_[0], copy - tail_copy));
    Stephen Nusko . resolved

    base::as_chars?

    Daniel Angulo

    Done

    Open in Gerrit

    Related details

    Attention is currently required from:
    • Arthur Sonzogni
    • Stephen Nusko
    Submit Requirements:
    • requirement satisfiedCode-Coverage
    • requirement is not satisfiedCode-Owners
    • requirement is not satisfiedCode-Review
    • requirement is not satisfiedNo-Unresolved-Comments
    • requirement is not satisfiedReview-Enforcement
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: comment
    Gerrit-Project: chromium/src
    Gerrit-Branch: main
    Gerrit-Change-Id: Id1a0ff3462edd3d7fa119beff620570f1893a0d8
    Gerrit-Change-Number: 7526157
    Gerrit-PatchSet: 5
    Gerrit-Owner: Daniel Angulo <angd...@google.com>
    Gerrit-Reviewer: Arthur Sonzogni <arthurs...@chromium.org>
    Gerrit-Reviewer: Daniel Angulo <angd...@google.com>
    Gerrit-Reviewer: Stephen Nusko <nus...@chromium.org>
    Gerrit-Attention: Stephen Nusko <nus...@chromium.org>
    Gerrit-Attention: Arthur Sonzogni <arthurs...@chromium.org>
    Gerrit-Comment-Date: Thu, 29 Jan 2026 20:03:00 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    Comment-In-Reply-To: Stephen Nusko <nus...@chromium.org>
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    Stephen Nusko (Gerrit)

    unread,
    Jan 29, 2026, 8:52:28 PMJan 29
    to Daniel Angulo, Arthur Sonzogni, AyeAye, Chromium LUCI CQ, chromotin...@chromium.org
    Attention needed from Arthur Sonzogni and Daniel Angulo

    Stephen Nusko added 7 comments

    File remoting/protocol/pseudo_tcp.cc
    Line 137, Patchset 2: base::as_writable_bytes(UNSAFE_BUFFERS(base::span(str, len)))
    Stephen Nusko . unresolved

    We can't claim UNSAFE_BUFFERS here, what SAFETY message would you write?

    We have 3 options
    1) Make this function take std::string_view
    2) Make this function UNSAFE_BUFFER_USAGE and force all callers to add UNSAFE_TODO or UNSAFE_BUFFERS
    3) Mark this as UNSAFE_TODO for now until someone can do 1 or 2.

    Daniel Angulo

    I was thinking that string_view can't be used because it needs to write data on it, but making this function take a span<char> would work instead. However this function is not used anywhare, should I stray it?

    Stephen Nusko

    If this function isn't used we should just delete it I think?

    I guess the API it is copied from has one, so we could keep it.

    Also I think std::string_view is fine? we are writing a string so accepting a string and converting it to bytes seems fine?

    Line 501, Patchset 5 (Latest): base::as_writable_bytes(UNSAFE_BUFFERS(base::span(buffer, len))),
    Stephen Nusko . unresolved

    We can't use UNSAFE_BUFFERS here still, we have the same issue as the other location.

    Line 558, Patchset 5 (Latest):uint32_t PseudoTcp::queue(const char* data, uint32_t len, bool bCtrl) {
    Stephen Nusko . unresolved

    Can we make this a span as well?

    Line 652, Patchset 5 (Latest): reader.Skip(1u);
    Stephen Nusko . unresolved

    What is this skip? isn't flags at position 13?

    `ack` = `buffer + 8` which is U32 so 4 bytes so ends at `buffer + 12`, and then we do `seq.flags = buffer[13]`; but in the new code we `Skip(1u)`?

    Line 750, Patchset 5 (Latest): parseOptions(seg.data.subspan(1u));
    Stephen Nusko . unresolved

    nit: template subspan<1u>

    Line 1385, Patchset 5 (Latest): const size_t tail_copy = std::min(copy, buffer_.size() - read_position_);

    new_buffer.subspan(0, tail_copy)
    .copy_from(buffer_.subspan(read_position_, tail_copy));
    new_buffer.subspan(tail_copy, copy - tail_copy)
    .copy_from(buffer_.subspan(0, copy - tail_copy));
    Stephen Nusko . unresolved

    could this be written as a base::span::split? I think so?

    Line 1479, Patchset 5 (Latest): base::span<char> dest = base::as_writable_chars(buffer);
    base::span<const char> src =
    base::as_chars(buffer_.subspan(read_position, tail_copy));
    dest.first(tail_copy).copy_from(src);
    base::span<const char> src2 =
    base::as_chars(buffer_.subspan(0, copy - tail_copy));
    dest.subspan(tail_copy, copy - tail_copy).copy_from(src2);
    Stephen Nusko . unresolved

    I didn't fully math this out but also feels like a split of some sort?

    Open in Gerrit

    Related details

    Attention is currently required from:
    • Arthur Sonzogni
    • Daniel Angulo
    Submit Requirements:
    • requirement satisfiedCode-Coverage
    • requirement is not satisfiedCode-Owners
    • requirement is not satisfiedCode-Review
    • requirement is not satisfiedNo-Unresolved-Comments
    • requirement is not satisfiedReview-Enforcement
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: comment
    Gerrit-Project: chromium/src
    Gerrit-Branch: main
    Gerrit-Change-Id: Id1a0ff3462edd3d7fa119beff620570f1893a0d8
    Gerrit-Change-Number: 7526157
    Gerrit-PatchSet: 5
    Gerrit-Owner: Daniel Angulo <angd...@google.com>
    Gerrit-Reviewer: Arthur Sonzogni <arthurs...@chromium.org>
    Gerrit-Reviewer: Daniel Angulo <angd...@google.com>
    Gerrit-Reviewer: Stephen Nusko <nus...@chromium.org>
    Gerrit-Attention: Daniel Angulo <angd...@google.com>
    Gerrit-Attention: Arthur Sonzogni <arthurs...@chromium.org>
    Gerrit-Comment-Date: Fri, 30 Jan 2026 01:51:55 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    Comment-In-Reply-To: Stephen Nusko <nus...@chromium.org>
    Comment-In-Reply-To: Daniel Angulo <angd...@google.com>
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    Daniel Angulo (Gerrit)

    unread,
    Jan 30, 2026, 11:30:01 AMJan 30
    to Arthur Sonzogni, Stephen Nusko, AyeAye, Chromium LUCI CQ, chromotin...@chromium.org
    Attention needed from Arthur Sonzogni and Stephen Nusko

    Daniel Angulo added 7 comments

    File remoting/protocol/pseudo_tcp.cc
    Line 137, Patchset 2: base::as_writable_bytes(UNSAFE_BUFFERS(base::span(str, len)))
    Stephen Nusko . unresolved

    We can't claim UNSAFE_BUFFERS here, what SAFETY message would you write?

    We have 3 options
    1) Make this function take std::string_view
    2) Make this function UNSAFE_BUFFER_USAGE and force all callers to add UNSAFE_TODO or UNSAFE_BUFFERS
    3) Mark this as UNSAFE_TODO for now until someone can do 1 or 2.

    Daniel Angulo

    I was thinking that string_view can't be used because it needs to write data on it, but making this function take a span<char> would work instead. However this function is not used anywhare, should I stray it?

    Stephen Nusko

    If this function isn't used we should just delete it I think?

    I guess the API it is copied from has one, so we could keep it.

    Also I think std::string_view is fine? we are writing a string so accepting a string and converting it to bytes seems fine?

    Daniel Angulo

    isn't it writing data+pos into the same str that is the parameter?

    Line 501, Patchset 5: base::as_writable_bytes(UNSAFE_BUFFERS(base::span(buffer, len))),
    Stephen Nusko . resolved

    We can't use UNSAFE_BUFFERS here still, we have the same issue as the other location.

    Daniel Angulo

    Done

    Line 558, Patchset 5:uint32_t PseudoTcp::queue(const char* data, uint32_t len, bool bCtrl) {
    Stephen Nusko . resolved

    Can we make this a span as well?

    Daniel Angulo

    Done

    Line 652, Patchset 5: reader.Skip(1u);
    Stephen Nusko . unresolved

    What is this skip? isn't flags at position 13?

    `ack` = `buffer + 8` which is U32 so 4 bytes so ends at `buffer + 12`, and then we do `seq.flags = buffer[13]`; but in the new code we `Skip(1u)`?

    Daniel Angulo

    in the writter we have buff[12] = 0; (which is the position 13) then buff[13] = flags (which is position 14). If I disable the skip then a bunch of tests start to fail

    Line 750, Patchset 5: parseOptions(seg.data.subspan(1u));
    Stephen Nusko . resolved

    nit: template subspan<1u>

    Daniel Angulo

    Done

    Line 1385, Patchset 5: const size_t tail_copy = std::min(copy, buffer_.size() - read_position_);


    new_buffer.subspan(0, tail_copy)
    .copy_from(buffer_.subspan(read_position_, tail_copy));
    new_buffer.subspan(tail_copy, copy - tail_copy)
    .copy_from(buffer_.subspan(0, copy - tail_copy));
    Stephen Nusko . resolved

    could this be written as a base::span::split? I think so?

    Daniel Angulo

    Done

    Line 1479, Patchset 5: base::span<char> dest = base::as_writable_chars(buffer);

    base::span<const char> src =
    base::as_chars(buffer_.subspan(read_position, tail_copy));
    dest.first(tail_copy).copy_from(src);
    base::span<const char> src2 =
    base::as_chars(buffer_.subspan(0, copy - tail_copy));
    dest.subspan(tail_copy, copy - tail_copy).copy_from(src2);
    Stephen Nusko . resolved

    I didn't fully math this out but also feels like a split of some sort?

    Daniel Angulo

    Done

    Open in Gerrit

    Related details

    Attention is currently required from:
    • Arthur Sonzogni
    • Stephen Nusko
    Submit Requirements:
    • requirement satisfiedCode-Coverage
    • requirement is not satisfiedCode-Owners
    • requirement is not satisfiedCode-Review
    • requirement is not satisfiedNo-Unresolved-Comments
    • requirement is not satisfiedReview-Enforcement
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: comment
    Gerrit-Project: chromium/src
    Gerrit-Branch: main
    Gerrit-Change-Id: Id1a0ff3462edd3d7fa119beff620570f1893a0d8
    Gerrit-Change-Number: 7526157
    Gerrit-PatchSet: 6
    Gerrit-Owner: Daniel Angulo <angd...@google.com>
    Gerrit-Reviewer: Arthur Sonzogni <arthurs...@chromium.org>
    Gerrit-Reviewer: Daniel Angulo <angd...@google.com>
    Gerrit-Reviewer: Stephen Nusko <nus...@chromium.org>
    Gerrit-Attention: Stephen Nusko <nus...@chromium.org>
    Gerrit-Attention: Arthur Sonzogni <arthurs...@chromium.org>
    Gerrit-Comment-Date: Fri, 30 Jan 2026 16:29:45 +0000
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    Stephen Nusko (Gerrit)

    unread,
    Feb 1, 2026, 11:50:17 PMFeb 1
    to Daniel Angulo, Arthur Sonzogni, AyeAye, Chromium LUCI CQ, chromotin...@chromium.org
    Attention needed from Arthur Sonzogni and Daniel Angulo

    Stephen Nusko added 11 comments

    File remoting/protocol/pseudo_tcp.cc
    Line 137, Patchset 2: base::as_writable_bytes(UNSAFE_BUFFERS(base::span(str, len)))
    Stephen Nusko . unresolved

    We can't claim UNSAFE_BUFFERS here, what SAFETY message would you write?

    We have 3 options
    1) Make this function take std::string_view
    2) Make this function UNSAFE_BUFFER_USAGE and force all callers to add UNSAFE_TODO or UNSAFE_BUFFERS
    3) Mark this as UNSAFE_TODO for now until someone can do 1 or 2.

    Daniel Angulo

    I was thinking that string_view can't be used because it needs to write data on it, but making this function take a span<char> would work instead. However this function is not used anywhare, should I stray it?

    Stephen Nusko

    If this function isn't used we should just delete it I think?

    I guess the API it is copied from has one, so we could keep it.

    Also I think std::string_view is fine? we are writing a string so accepting a string and converting it to bytes seems fine?

    Daniel Angulo

    isn't it writing data+pos into the same str that is the parameter?

    Stephen Nusko

    Obviously a char span works, but an std::string_view can be converted to a span cheaply so I'm not sure I follow the concern?

    Since you already have to do base::as_writable_byte_span there is no difference but API clarity that you have a string? So better to use an std::string_view no?

    Line 140, Patchset 6 (Latest): // SAFETY: `str` is a raw char*, but we immediately convert it to a span of
    // bytes, which makes our intentions clear and prevents buffer overflows.
    Stephen Nusko . unresolved

    No need for a safety comment.

    Line 590, Patchset 6 (Latest): base::span<uint8_t> buffer(buffer_storage);
    Stephen Nusko . unresolved

    You don't need this variable, just pass `buffer_storage` directly into the SpanWriter.

    And use the `subspan` method on `buffer_storage` directly for ReadOffset call.

    Line 652, Patchset 5: reader.Skip(1u);
    Stephen Nusko . unresolved

    What is this skip? isn't flags at position 13?

    `ack` = `buffer + 8` which is U32 so 4 bytes so ends at `buffer + 12`, and then we do `seq.flags = buffer[13]`; but in the new code we `Skip(1u)`?

    Daniel Angulo

    in the writter we have buff[12] = 0; (which is the position 13) then buff[13] = flags (which is position 14). If I disable the skip then a bunch of tests start to fail

    Stephen Nusko

    Perfect can you add a comment mentioning this? Makes sense.

    Line 1260, Patchset 6 (Latest): // SAFETY: buf.Data() is a pointer to uint8_t of size buf.Length(), and we
    // cast it to a pointer to char of that size.
    queue(UNSAFE_BUFFERS(base::span(reinterpret_cast<const char*>(buf.Data()),
    static_cast<uint32_t>(buf.Length()))),
    Stephen Nusko . unresolved

    We own the ByteBufferWriter type here in our code, and are already modifying it. Can we just add a data() and size() method to it so it can directly construct a span and then we can use `as_writable_bytes`?

    Then remove the SAFETY comment.

    Line 1389, Patchset 6 (Latest): new_buffer_first.copy_from(buffer_.subspan(read_position_, tail_copy));
    Stephen Nusko . unresolved

    copy_from_nonoverlapping (these are separate heap arrays they can't be the same memory).

    Line 1503, Patchset 6 (Latest): const size_t tail_copy = std::min(copy, buffer_.size() - write_position);
    buffer_.subspan(write_position, tail_copy)
    .copy_from(base::as_chars(buffer.first(tail_copy)));
    buffer_.first(copy - tail_copy)
    .copy_from(base::as_chars(buffer.subspan(tail_copy, copy - tail_copy)));
    Stephen Nusko . unresolved

    Switch this into a split as well?

    File remoting/protocol/pseudo_tcp_unittest.cc
    Line 196, Patchset 6 (Latest): UNSAFE_BUFFERS(base::span(packet.c_str(), packet.size())));
    Stephen Nusko . unresolved

    We don't need this UNSAFE_BUFFERS

    Just make a string_view or use `base::as_writable_chars`

    Line 361, Patchset 6 (Latest): received = remote_.Recv(base::span(block).first(block.size()));
    Stephen Nusko . unresolved

    first(block.size) of a span of block doesn't make any difference. Remove .first()

    Line 525, Patchset 6 (Latest): received = receiver_->Recv(base::span(block).first(block.size()));
    Stephen Nusko . unresolved

    Also review this and other calls for redundant first calls.

    File remoting/protocol/pseudotcp_adapter.cc
    Line 166, Patchset 6 (Latest): base::span(buffer->data(), static_cast<size_t>(buffer_size))));
    Stephen Nusko . unresolved

    Can't you juse use `buffer.span()`? here and below?

    Open in Gerrit

    Related details

    Attention is currently required from:
    • Arthur Sonzogni
    • Daniel Angulo
    Submit Requirements:
    • requirement satisfiedCode-Coverage
    • requirement is not satisfiedCode-Owners
    • requirement is not satisfiedCode-Review
    • requirement is not satisfiedNo-Unresolved-Comments
    • requirement is not satisfiedReview-Enforcement
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: comment
    Gerrit-Project: chromium/src
    Gerrit-Branch: main
    Gerrit-Change-Id: Id1a0ff3462edd3d7fa119beff620570f1893a0d8
    Gerrit-Change-Number: 7526157
    Gerrit-PatchSet: 6
    Gerrit-Owner: Daniel Angulo <angd...@google.com>
    Gerrit-Reviewer: Arthur Sonzogni <arthurs...@chromium.org>
    Gerrit-Reviewer: Daniel Angulo <angd...@google.com>
    Gerrit-Reviewer: Stephen Nusko <nus...@chromium.org>
    Gerrit-Attention: Daniel Angulo <angd...@google.com>
    Gerrit-Attention: Arthur Sonzogni <arthurs...@chromium.org>
    Gerrit-Comment-Date: Mon, 02 Feb 2026 04:49:46 +0000
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    Arthur Sonzogni (Gerrit)

    unread,
    Feb 10, 2026, 8:51:21 AM (12 days ago) Feb 10
    to Daniel Angulo, Code Review Nudger, Stephen Nusko, AyeAye, Chromium LUCI CQ, chromotin...@chromium.org
    Attention needed from Daniel Angulo

    Arthur Sonzogni added 1 comment

    Patchset-level comments
    File-level comment, Patchset 6 (Latest):
    Arthur Sonzogni . unresolved

    Thanks!
    (I am waiting for the current suggestion to be addressed + the build to pass)
    Feel free to close this comment when this patch is ready to be reviewed again.

    Open in Gerrit

    Related details

    Attention is currently required from:
    • Daniel Angulo
    Submit Requirements:
    • requirement satisfiedCode-Coverage
    • requirement is not satisfiedCode-Owners
    • requirement is not satisfiedCode-Review
    • requirement is not satisfiedNo-Unresolved-Comments
    • requirement is not satisfiedReview-Enforcement
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: comment
    Gerrit-Project: chromium/src
    Gerrit-Branch: main
    Gerrit-Change-Id: Id1a0ff3462edd3d7fa119beff620570f1893a0d8
    Gerrit-Change-Number: 7526157
    Gerrit-PatchSet: 6
    Gerrit-Owner: Daniel Angulo <angd...@google.com>
    Gerrit-Reviewer: Arthur Sonzogni <arthurs...@chromium.org>
    Gerrit-Reviewer: Daniel Angulo <angd...@google.com>
    Gerrit-Reviewer: Stephen Nusko <nus...@chromium.org>
    Gerrit-CC: Code Review Nudger <android-build...@prod.google.com>
    Gerrit-Attention: Daniel Angulo <angd...@google.com>
    Gerrit-Comment-Date: Tue, 10 Feb 2026 13:51:07 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    Daniel Angulo (Gerrit)

    unread,
    Feb 10, 2026, 4:48:26 PM (11 days ago) Feb 10
    to Code Review Nudger, Arthur Sonzogni, Stephen Nusko, AyeAye, Chromium LUCI CQ, chromotin...@chromium.org
    Attention needed from Arthur Sonzogni and Stephen Nusko

    Daniel Angulo added 13 comments

    Patchset-level comments
    File-level comment, Patchset 6:
    Arthur Sonzogni . resolved

    Thanks!
    (I am waiting for the current suggestion to be addressed + the build to pass)
    Feel free to close this comment when this patch is ready to be reviewed again.

    Daniel Angulo

    Done

    File remoting/protocol/pseudo_tcp.cc
    Line 137, Patchset 2: base::as_writable_bytes(UNSAFE_BUFFERS(base::span(str, len)))
    Stephen Nusko . unresolved

    We can't claim UNSAFE_BUFFERS here, what SAFETY message would you write?

    We have 3 options
    1) Make this function take std::string_view
    2) Make this function UNSAFE_BUFFER_USAGE and force all callers to add UNSAFE_TODO or UNSAFE_BUFFERS
    3) Mark this as UNSAFE_TODO for now until someone can do 1 or 2.

    Daniel Angulo

    I was thinking that string_view can't be used because it needs to write data on it, but making this function take a span<char> would work instead. However this function is not used anywhare, should I stray it?

    Stephen Nusko

    If this function isn't used we should just delete it I think?

    I guess the API it is copied from has one, so we could keep it.

    Also I think std::string_view is fine? we are writing a string so accepting a string and converting it to bytes seems fine?

    Daniel Angulo

    isn't it writing data+pos into the same str that is the parameter?

    Stephen Nusko

    Obviously a char span works, but an std::string_view can be converted to a span cheaply so I'm not sure I follow the concern?

    Since you already have to do base::as_writable_byte_span there is no difference but API clarity that you have a string? So better to use an std::string_view no?

    Daniel Angulo

    base::as_writable_byte_span cannot be used with a std::string_view. Here's why

    std::string_view is Read-Only: A std::string_view (and absl::string_view) provides a non-owning, read-only view into an existing character sequence. It doesn't own the data and cannot be used to modify it.

    Line 140, Patchset 6: // SAFETY: `str` is a raw char*, but we immediately convert it to a span of

    // bytes, which makes our intentions clear and prevents buffer overflows.
    Stephen Nusko . resolved

    No need for a safety comment.

    Daniel Angulo

    Done

    Line 590, Patchset 6: base::span<uint8_t> buffer(buffer_storage);
    Stephen Nusko . resolved

    You don't need this variable, just pass `buffer_storage` directly into the SpanWriter.

    And use the `subspan` method on `buffer_storage` directly for ReadOffset call.

    Daniel Angulo
    no viable constructor or deduction guide for deduction of template arguments of 'base::SpanWriter'
    589 | base::SpanWriter writer(buffer_storage);
    Line 652, Patchset 5: reader.Skip(1u);
    Stephen Nusko . resolved

    What is this skip? isn't flags at position 13?

    `ack` = `buffer + 8` which is U32 so 4 bytes so ends at `buffer + 12`, and then we do `seq.flags = buffer[13]`; but in the new code we `Skip(1u)`?

    Daniel Angulo

    in the writter we have buff[12] = 0; (which is the position 13) then buff[13] = flags (which is position 14). If I disable the skip then a bunch of tests start to fail

    Stephen Nusko

    Perfect can you add a comment mentioning this? Makes sense.

    Daniel Angulo

    Done

    Line 1260, Patchset 6: // SAFETY: buf.Data() is a pointer to uint8_t of size buf.Length(), and we

    // cast it to a pointer to char of that size.
    queue(UNSAFE_BUFFERS(base::span(reinterpret_cast<const char*>(buf.Data()),
    static_cast<uint32_t>(buf.Length()))),
    Stephen Nusko . resolved

    We own the ByteBufferWriter type here in our code, and are already modifying it. Can we just add a data() and size() method to it so it can directly construct a span and then we can use `as_writable_bytes`?

    Then remove the SAFETY comment.

    Daniel Angulo

    Done

    Line 1389, Patchset 6: new_buffer_first.copy_from(buffer_.subspan(read_position_, tail_copy));
    Stephen Nusko . resolved

    copy_from_nonoverlapping (these are separate heap arrays they can't be the same memory).

    Daniel Angulo

    Done

    Line 1385, Patchset 5: const size_t tail_copy = std::min(copy, buffer_.size() - read_position_);

    new_buffer.subspan(0, tail_copy)
    .copy_from(buffer_.subspan(read_position_, tail_copy));
    new_buffer.subspan(tail_copy, copy - tail_copy)
    .copy_from(buffer_.subspan(0, copy - tail_copy));
    Stephen Nusko . resolved

    could this be written as a base::span::split? I think so?

    Daniel Angulo

    Done

    Daniel Angulo

    how? I see that there could be a split at tail_copy, but buffer_.subspan(0, copy - tail_copy) starts at offset 0 not at tail_copy, maybe I'm just a little bit confused but I don't see a clean split

    Line 1503, Patchset 6: const size_t tail_copy = std::min(copy, buffer_.size() - write_position);

    buffer_.subspan(write_position, tail_copy)
    .copy_from(base::as_chars(buffer.first(tail_copy)));
    buffer_.first(copy - tail_copy)
    .copy_from(base::as_chars(buffer.subspan(tail_copy, copy - tail_copy)));
    Stephen Nusko . resolved

    Switch this into a split as well?

    Daniel Angulo

    Done

    File remoting/protocol/pseudo_tcp_unittest.cc
    Line 196, Patchset 6: UNSAFE_BUFFERS(base::span(packet.c_str(), packet.size())));
    Stephen Nusko . resolved

    We don't need this UNSAFE_BUFFERS

    Just make a string_view or use `base::as_writable_chars`

    Daniel Angulo

    Done

    Line 361, Patchset 6: received = remote_.Recv(base::span(block).first(block.size()));
    Stephen Nusko . resolved

    first(block.size) of a span of block doesn't make any difference. Remove .first()

    Daniel Angulo

    Done

    Line 525, Patchset 6: received = receiver_->Recv(base::span(block).first(block.size()));
    Stephen Nusko . resolved

    Also review this and other calls for redundant first calls.

    Daniel Angulo

    Done

    File remoting/protocol/pseudotcp_adapter.cc
    Line 166, Patchset 6: base::span(buffer->data(), static_cast<size_t>(buffer_size))));
    Stephen Nusko . resolved

    Can't you juse use `buffer.span()`? here and below?

    Daniel Angulo

    Done

    Open in Gerrit

    Related details

    Attention is currently required from:
    • Arthur Sonzogni
    • Stephen Nusko
    Submit Requirements:
    • requirement satisfiedCode-Coverage
    • requirement is not satisfiedCode-Owners
    • requirement is not satisfiedCode-Review
    • requirement is not satisfiedNo-Unresolved-Comments
    • requirement is not satisfiedReview-Enforcement
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: comment
    Gerrit-Project: chromium/src
    Gerrit-Branch: main
    Gerrit-Change-Id: Id1a0ff3462edd3d7fa119beff620570f1893a0d8
    Gerrit-Change-Number: 7526157
    Gerrit-PatchSet: 8
    Gerrit-Owner: Daniel Angulo <angd...@google.com>
    Gerrit-Reviewer: Arthur Sonzogni <arthurs...@chromium.org>
    Gerrit-Reviewer: Daniel Angulo <angd...@google.com>
    Gerrit-Reviewer: Stephen Nusko <nus...@chromium.org>
    Gerrit-CC: Code Review Nudger <android-build...@prod.google.com>
    Gerrit-Attention: Stephen Nusko <nus...@chromium.org>
    Gerrit-Attention: Arthur Sonzogni <arthurs...@chromium.org>
    Gerrit-Comment-Date: Tue, 10 Feb 2026 21:48:18 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    Comment-In-Reply-To: Stephen Nusko <nus...@chromium.org>
    Comment-In-Reply-To: Daniel Angulo <angd...@google.com>
    Comment-In-Reply-To: Arthur Sonzogni <arthurs...@chromium.org>
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    Arthur Sonzogni (Gerrit)

    unread,
    Feb 12, 2026, 4:26:33 AM (10 days ago) Feb 12
    to Daniel Angulo, Code Review Nudger, Stephen Nusko, AyeAye, Chromium LUCI CQ, chromotin...@chromium.org
    Attention needed from Daniel Angulo and Stephen Nusko

    Arthur Sonzogni added 6 comments

    File remoting/protocol/pseudo_tcp.cc
    Line 498, Patchset 8 (Latest):int PseudoTcp::Recv(base::span<char> buffer) {
    Arthur Sonzogni . unresolved

    Could this be uint8_t?

    Line 505, Patchset 8 (Latest): if (!m_rbuf.Read(base::as_writable_bytes(buffer), &read)) {
    Arthur Sonzogni . unresolved

    This can be removed after applying my previous comment.

    File remoting/protocol/pseudotcp_adapter.cc
    Line 156, Patchset 8 (Latest): int buffer_size,
    Arthur Sonzogni . unresolved

    Can we `CHECK_EQ(buffer->span().size(), buffer_size)`.

    Eventually, the `buffer_size` argument would be removed, but this is going to take additional refactoring.

    Line 162, Patchset 8 (Latest):
    // SAFETY: buffer_size is the size of the buffer, and the buffer is a pointer
    // to char of that size.
    Arthur Sonzogni . unresolved

    We don't need a "safety" comment here. There are no UNSAFE_BUFERS

    Line 165, Patchset 8 (Latest): int result = pseudo_tcp_.Recv(base::as_writable_chars(buffer->span()));
    Arthur Sonzogni . unresolved

    This can be removed if you apply one of my other comments about passing `base::span<uint8_t>`

    Line 184, Patchset 8 (Latest): int buffer_size,
    Arthur Sonzogni . unresolved

    ditto

    Open in Gerrit

    Related details

    Attention is currently required from:
    • Daniel Angulo
    • Stephen Nusko
    Submit Requirements:
    • requirement satisfiedCode-Coverage
    • requirement is not satisfiedCode-Owners
    • requirement is not satisfiedCode-Review
    • requirement is not satisfiedNo-Unresolved-Comments
    • requirement is not satisfiedReview-Enforcement
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: comment
    Gerrit-Project: chromium/src
    Gerrit-Branch: main
    Gerrit-Change-Id: Id1a0ff3462edd3d7fa119beff620570f1893a0d8
    Gerrit-Change-Number: 7526157
    Gerrit-PatchSet: 8
    Gerrit-Owner: Daniel Angulo <angd...@google.com>
    Gerrit-Reviewer: Arthur Sonzogni <arthurs...@chromium.org>
    Gerrit-Reviewer: Daniel Angulo <angd...@google.com>
    Gerrit-Reviewer: Stephen Nusko <nus...@chromium.org>
    Gerrit-CC: Code Review Nudger <android-build...@prod.google.com>
    Gerrit-Attention: Stephen Nusko <nus...@chromium.org>
    Gerrit-Attention: Daniel Angulo <angd...@google.com>
    Gerrit-Comment-Date: Thu, 12 Feb 2026 09:26:20 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    Daniel Angulo (Gerrit)

    unread,
    Feb 12, 2026, 12:27:03 PM (9 days ago) Feb 12
    to Code Review Nudger, Arthur Sonzogni, Stephen Nusko, AyeAye, Chromium LUCI CQ, chromotin...@chromium.org
    Attention needed from Arthur Sonzogni and Stephen Nusko

    Daniel Angulo added 5 comments

    File remoting/protocol/pseudo_tcp.cc
    Line 498, Patchset 8:int PseudoTcp::Recv(base::span<char> buffer) {
    Arthur Sonzogni . resolved

    Could this be uint8_t?

    Daniel Angulo

    Done

    Line 505, Patchset 8: if (!m_rbuf.Read(base::as_writable_bytes(buffer), &read)) {
    Arthur Sonzogni . resolved

    This can be removed after applying my previous comment.

    Daniel Angulo

    Done

    File remoting/protocol/pseudotcp_adapter.cc
    Line 156, Patchset 8: int buffer_size,
    Arthur Sonzogni . unresolved

    Can we `CHECK_EQ(buffer->span().size(), buffer_size)`.

    Eventually, the `buffer_size` argument would be removed, but this is going to take additional refactoring.

    Daniel Angulo

    check_eq is throwing error because buffer->span() and buffer_size are not equal, have just added .first(buffer_size) to the Recv call


    // SAFETY: buffer_size is the size of the buffer, and the buffer is a pointer
    // to char of that size.
    Arthur Sonzogni . resolved

    We don't need a "safety" comment here. There are no UNSAFE_BUFERS

    Daniel Angulo

    Done

    Line 165, Patchset 8: int result = pseudo_tcp_.Recv(base::as_writable_chars(buffer->span()));
    Arthur Sonzogni . resolved

    This can be removed if you apply one of my other comments about passing `base::span<uint8_t>`

    Daniel Angulo

    Done

    Open in Gerrit

    Related details

    Attention is currently required from:
    • Arthur Sonzogni
    • Stephen Nusko
    Submit Requirements:
    • requirement satisfiedCode-Coverage
    • requirement is not satisfiedCode-Owners
    • requirement is not satisfiedCode-Review
    • requirement is not satisfiedNo-Unresolved-Comments
    • requirement is not satisfiedReview-Enforcement
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: comment
    Gerrit-Project: chromium/src
    Gerrit-Branch: main
    Gerrit-Change-Id: Id1a0ff3462edd3d7fa119beff620570f1893a0d8
    Gerrit-Change-Number: 7526157
    Gerrit-PatchSet: 9
    Gerrit-Owner: Daniel Angulo <angd...@google.com>
    Gerrit-Reviewer: Arthur Sonzogni <arthurs...@chromium.org>
    Gerrit-Reviewer: Daniel Angulo <angd...@google.com>
    Gerrit-Reviewer: Stephen Nusko <nus...@chromium.org>
    Gerrit-CC: Code Review Nudger <android-build...@prod.google.com>
    Gerrit-Attention: Stephen Nusko <nus...@chromium.org>
    Gerrit-Attention: Arthur Sonzogni <arthurs...@chromium.org>
    Gerrit-Comment-Date: Thu, 12 Feb 2026 17:26:54 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    Comment-In-Reply-To: Arthur Sonzogni <arthurs...@chromium.org>
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    Arthur Sonzogni (Gerrit)

    unread,
    Feb 13, 2026, 10:07:29 AM (9 days ago) Feb 13
    to Daniel Angulo, Code Review Nudger, Stephen Nusko, AyeAye, Chromium LUCI CQ, chromotin...@chromium.org
    Attention needed from Daniel Angulo and Stephen Nusko

    Arthur Sonzogni added 6 comments

    File remoting/protocol/pseudo_tcp.h
    Line 81, Patchset 9 (Latest): bool NotifyPacket(base::span<const char> buffer);
    Arthur Sonzogni . unresolved

    Optional: Ma

    File remoting/protocol/pseudotcp_adapter.cc
    Line 162, Patchset 9 (Latest): int result = pseudo_tcp_.Recv(buffer->span().first(buffer_size));
    Arthur Sonzogni . unresolved

    This could be `first` directly.

    Line 189, Patchset 9 (Latest): int result = pseudo_tcp_.Send(buffer->span().first(buffer_size));
    Arthur Sonzogni . unresolved

    this could be `first`

    Line 261, Patchset 9 (Latest): // SAFETY: read_buffer_size_ is the size of the buffer, and the buffer is a
    // pointer to char of that size.
    int result = pseudo_tcp_.Recv(UNSAFE_BUFFERS(
    base::span(reinterpret_cast<uint8_t*>(read_buffer_->data()),
    static_cast<size_t>(read_buffer_size_))));
    Arthur Sonzogni . unresolved

    We could avoid `UNSAFE_BUFFERS`, here because `read_buffer_->first(read_buffer_size_)` exist.

    (There is also `->span()` for the full span)

    Line 290, Patchset 9 (Latest):
    // SAFETY: write_buffer_size_ is the size of the buffer, and the buffer is a
    // pointer to char of that size.
    int result = pseudo_tcp_.Send(UNSAFE_BUFFERS(
    base::span(reinterpret_cast<uint8_t*>(write_buffer_->data()),
    static_cast<size_t>(write_buffer_size_))));
    Arthur Sonzogni . unresolved

    Ditto

    Line 433, Patchset 9 (Latest): pseudo_tcp_.NotifyPacket(UNSAFE_BUFFERS(
    Arthur Sonzogni . unresolved

    Ditto

    Open in Gerrit

    Related details

    Attention is currently required from:
    • Daniel Angulo
    • Stephen Nusko
    Submit Requirements:
    • requirement satisfiedCode-Coverage
    • requirement is not satisfiedCode-Owners
    • requirement is not satisfiedCode-Review
    • requirement is not satisfiedNo-Unresolved-Comments
    • requirement is not satisfiedReview-Enforcement
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: comment
    Gerrit-Project: chromium/src
    Gerrit-Branch: main
    Gerrit-Change-Id: Id1a0ff3462edd3d7fa119beff620570f1893a0d8
    Gerrit-Change-Number: 7526157
    Gerrit-PatchSet: 9
    Gerrit-Owner: Daniel Angulo <angd...@google.com>
    Gerrit-Reviewer: Arthur Sonzogni <arthurs...@chromium.org>
    Gerrit-Reviewer: Daniel Angulo <angd...@google.com>
    Gerrit-Reviewer: Stephen Nusko <nus...@chromium.org>
    Gerrit-CC: Code Review Nudger <android-build...@prod.google.com>
    Gerrit-Attention: Stephen Nusko <nus...@chromium.org>
    Gerrit-Attention: Daniel Angulo <angd...@google.com>
    Gerrit-Comment-Date: Fri, 13 Feb 2026 15:07:12 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    Daniel Angulo (Gerrit)

    unread,
    Feb 13, 2026, 4:59:24 PM (8 days ago) Feb 13
    to Code Review Nudger, Arthur Sonzogni, Stephen Nusko, AyeAye, Chromium LUCI CQ, chromotin...@chromium.org
    Attention needed from Arthur Sonzogni and Stephen Nusko

    Daniel Angulo added 7 comments

    File remoting/protocol/pseudo_tcp.h
    Line 81, Patchset 9: bool NotifyPacket(base::span<const char> buffer);
    Arthur Sonzogni . resolved

    Optional: Ma

    Daniel Angulo

    Ma?

    File remoting/protocol/pseudotcp_adapter.cc
    Line 162, Patchset 9: int result = pseudo_tcp_.Recv(buffer->span().first(buffer_size));
    Arthur Sonzogni . resolved

    This could be `first` directly.

    Daniel Angulo

    Done

    Line 184, Patchset 8: int buffer_size,
    Arthur Sonzogni . resolved

    ditto

    Daniel Angulo

    Done

    Line 189, Patchset 9: int result = pseudo_tcp_.Send(buffer->span().first(buffer_size));
    Arthur Sonzogni . resolved

    this could be `first`

    Daniel Angulo

    Done

    Line 261, Patchset 9: // SAFETY: read_buffer_size_ is the size of the buffer, and the buffer is a

    // pointer to char of that size.
    int result = pseudo_tcp_.Recv(UNSAFE_BUFFERS(
    base::span(reinterpret_cast<uint8_t*>(read_buffer_->data()),
    static_cast<size_t>(read_buffer_size_))));
    Arthur Sonzogni . resolved

    We could avoid `UNSAFE_BUFFERS`, here because `read_buffer_->first(read_buffer_size_)` exist.

    (There is also `->span()` for the full span)

    Daniel Angulo

    Done


    // SAFETY: write_buffer_size_ is the size of the buffer, and the buffer is a
    // pointer to char of that size.
    int result = pseudo_tcp_.Send(UNSAFE_BUFFERS(
    base::span(reinterpret_cast<uint8_t*>(write_buffer_->data()),
    static_cast<size_t>(write_buffer_size_))));
    Arthur Sonzogni . resolved

    Ditto

    Daniel Angulo

    Done

    Line 433, Patchset 9: pseudo_tcp_.NotifyPacket(UNSAFE_BUFFERS(
    Arthur Sonzogni . resolved

    Ditto

    Daniel Angulo

    Done

    Open in Gerrit

    Related details

    Attention is currently required from:
    • Arthur Sonzogni
    • Stephen Nusko
    Submit Requirements:
    • requirement satisfiedCode-Coverage
    • requirement is not satisfiedCode-Owners
    • requirement is not satisfiedCode-Review
    • requirement is not satisfiedNo-Unresolved-Comments
    • requirement is not satisfiedReview-Enforcement
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: comment
    Gerrit-Project: chromium/src
    Gerrit-Branch: main
    Gerrit-Change-Id: Id1a0ff3462edd3d7fa119beff620570f1893a0d8
    Gerrit-Change-Number: 7526157
    Gerrit-PatchSet: 10
    Gerrit-Owner: Daniel Angulo <angd...@google.com>
    Gerrit-Reviewer: Arthur Sonzogni <arthurs...@chromium.org>
    Gerrit-Reviewer: Daniel Angulo <angd...@google.com>
    Gerrit-Reviewer: Stephen Nusko <nus...@chromium.org>
    Gerrit-CC: Code Review Nudger <android-build...@prod.google.com>
    Gerrit-Attention: Stephen Nusko <nus...@chromium.org>
    Gerrit-Attention: Arthur Sonzogni <arthurs...@chromium.org>
    Gerrit-Comment-Date: Fri, 13 Feb 2026 21:59:18 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    Comment-In-Reply-To: Arthur Sonzogni <arthurs...@chromium.org>
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    Daniel Angulo (Gerrit)

    unread,
    Feb 13, 2026, 5:01:46 PM (8 days ago) Feb 13
    to Code Review Nudger, Arthur Sonzogni, Stephen Nusko, AyeAye, Chromium LUCI CQ, chromotin...@chromium.org
    Attention needed from Arthur Sonzogni and Stephen Nusko

    Daniel Angulo added 1 comment

    File remoting/protocol/pseudo_tcp.h
    Line 81, Patchset 9: bool NotifyPacket(base::span<const char> buffer);
    Arthur Sonzogni . unresolved

    Optional: Ma

    Daniel Angulo

    Ma?

    Daniel Angulo

    sorry, what did you say?

    Open in Gerrit

    Related details

    Attention is currently required from:
    • Arthur Sonzogni
    • Stephen Nusko
    Submit Requirements:
    • requirement satisfiedCode-Coverage
    • requirement is not satisfiedCode-Owners
    • requirement is not satisfiedCode-Review
    • requirement is not satisfiedNo-Unresolved-Comments
    • requirement is not satisfiedReview-Enforcement
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: comment
    Gerrit-Project: chromium/src
    Gerrit-Branch: main
    Gerrit-Change-Id: Id1a0ff3462edd3d7fa119beff620570f1893a0d8
    Gerrit-Change-Number: 7526157
    Gerrit-PatchSet: 11
    Gerrit-Owner: Daniel Angulo <angd...@google.com>
    Gerrit-Reviewer: Arthur Sonzogni <arthurs...@chromium.org>
    Gerrit-Reviewer: Daniel Angulo <angd...@google.com>
    Gerrit-Reviewer: Stephen Nusko <nus...@chromium.org>
    Gerrit-CC: Code Review Nudger <android-build...@prod.google.com>
    Gerrit-Attention: Stephen Nusko <nus...@chromium.org>
    Gerrit-Attention: Arthur Sonzogni <arthurs...@chromium.org>
    Gerrit-Comment-Date: Fri, 13 Feb 2026 22:01:41 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    Stephen Nusko (Gerrit)

    unread,
    Feb 15, 2026, 10:02:47 PM (6 days ago) Feb 15
    to Daniel Angulo, Code Review Nudger, Arthur Sonzogni, AyeAye, Chromium LUCI CQ, chromotin...@chromium.org
    Attention needed from Arthur Sonzogni and Daniel Angulo

    Stephen Nusko added 9 comments

    File remoting/protocol/pseudo_tcp.h
    Line 123, Patchset 11 (Latest): base::raw_span<const uint8_t> data;
    Stephen Nusko . unresolved

    Do we know if there is any benchmarks around this code? This is the line most likely to trigger potential performance impact as we create and destroy segments.

    File remoting/protocol/pseudo_tcp.cc
    Line 99, Patchset 11 (Latest): void WriteString(const char* str, size_t len) {

    // SAFETY: `str` is a raw char*, but we immediately convert it to a span of
    // bytes, which makes our intentions clear and prevents buffer overflows.
    auto bytes = base::as_byte_span(UNSAFE_BUFFERS(base::span(str, len)));
    Stephen Nusko . unresolved

    There is no caller of this function? Lets just switch it to a span? or delete it.

    Line 124, Patchset 11 (Latest): *val = base::U32FromBigEndian(data_.subspan(pos_).first<4u>());
    Stephen Nusko . unresolved

    Should we continue to use base::NetToHost32? Here and below to keep the convention?

    Line 137, Patchset 2: base::as_writable_bytes(UNSAFE_BUFFERS(base::span(str, len)))
    Stephen Nusko . resolved

    We can't claim UNSAFE_BUFFERS here, what SAFETY message would you write?

    We have 3 options
    1) Make this function take std::string_view
    2) Make this function UNSAFE_BUFFER_USAGE and force all callers to add UNSAFE_TODO or UNSAFE_BUFFERS
    3) Mark this as UNSAFE_TODO for now until someone can do 1 or 2.

    Daniel Angulo

    I was thinking that string_view can't be used because it needs to write data on it, but making this function take a span<char> would work instead. However this function is not used anywhare, should I stray it?

    Stephen Nusko

    If this function isn't used we should just delete it I think?

    I guess the API it is copied from has one, so we could keep it.

    Also I think std::string_view is fine? we are writing a string so accepting a string and converting it to bytes seems fine?

    Daniel Angulo

    isn't it writing data+pos into the same str that is the parameter?

    Stephen Nusko

    Obviously a char span works, but an std::string_view can be converted to a span cheaply so I'm not sure I follow the concern?

    Since you already have to do base::as_writable_byte_span there is no difference but API clarity that you have a string? So better to use an std::string_view no?

    Daniel Angulo

    base::as_writable_byte_span cannot be used with a std::string_view. Here's why

    std::string_view is Read-Only: A std::string_view (and absl::string_view) provides a non-owning, read-only view into an existing character sequence. It doesn't own the data and cannot be used to modify it.

    Stephen Nusko

    Ah right makes sense.

    Line 590, Patchset 6: base::span<uint8_t> buffer(buffer_storage);
    Stephen Nusko . resolved

    You don't need this variable, just pass `buffer_storage` directly into the SpanWriter.

    And use the `subspan` method on `buffer_storage` directly for ReadOffset call.

    Daniel Angulo
    no viable constructor or deduction guide for deduction of template arguments of 'base::SpanWriter'
    589 | base::SpanWriter writer(buffer_storage);
    Stephen Nusko

    I still prefer colapsing this to a single line:

    ```
    base::SpanWriter writer(base::span(buffer_storage));
    ```

    Also I think you might be able to do it with a template specification.

    ```
    base::SpanWriter<uint8_t> writer(buffer_storage);
    ```

    Which should remove one layer of guess work for the compiler.

    Both seem more readable to me then a variable we don't use again

    Line 652, Patchset 5: reader.Skip(1u);
    Stephen Nusko . unresolved

    What is this skip? isn't flags at position 13?

    `ack` = `buffer + 8` which is U32 so 4 bytes so ends at `buffer + 12`, and then we do `seq.flags = buffer[13]`; but in the new code we `Skip(1u)`?

    Daniel Angulo

    in the writter we have buff[12] = 0; (which is the position 13) then buff[13] = flags (which is position 14). If I disable the skip then a bunch of tests start to fail

    Stephen Nusko

    Perfect can you add a comment mentioning this? Makes sense.

    Daniel Angulo

    Done

    Stephen Nusko

    I'm sorry I don't see the comment?

    Just something like.

    ```
    reader.Skip(1u); // Skip the zero byte.
    ```
    Line 1385, Patchset 5: const size_t tail_copy = std::min(copy, buffer_.size() - read_position_);

    new_buffer.subspan(0, tail_copy)
    .copy_from(buffer_.subspan(read_position_, tail_copy));
    new_buffer.subspan(tail_copy, copy - tail_copy)
    .copy_from(buffer_.subspan(0, copy - tail_copy));
    Stephen Nusko . unresolved

    could this be written as a base::span::split? I think so?

    Daniel Angulo

    Done

    Daniel Angulo

    how? I see that there could be a split at tail_copy, but buffer_.subspan(0, copy - tail_copy) starts at offset 0 not at tail_copy, maybe I'm just a little bit confused but I don't see a clean split

    Stephen Nusko

    I like this already better because the copy is clear what is going into what. But I think we can do the other as well.


    ```
    auto new_buffer = base::HeapArray<uint8_t>::WithSize(size);

    const size_t copy = data_length_;

    const size_t tail_copy = std::min(copy, buffer_.size() - read_position_);

        // Split `new_buffer` into |:tail_copy:|:copy - tail_copy:| spans.
    auto [new_buffer_first, new_buffer_last] =
    new_buffer.as_span().first(copy).split_at(tail_copy);
    // Split `buffer` into | buffer_.size() - read_position | read_position |
    auto [before_read, after_read_position] =
    buffer_.as_span().split_at(read_position_);
    // Note: size > data_length_, but buffer_.size() >= data_length_ and unknown relation to size.
    // Any value after read_position_ is the |tail_copy|, but before_read
    // could be larger then the remaining |tail_copy - copy| so we adjust
    // it to make them equal (old_buffer_end might be empty).
    CHECK_EQ(old_buffer_start.size(), tail_copy);
    old_buffer_end = old_buffer_end.first(tail_copy-copy);

    new_buffer_first.copy_from_nonoverlapping(old_buffer_start);
    new_buffer_last.copy_from_nonoverlapping(old_buffer_end);
    ```

    Or something like that?

    File remoting/protocol/pseudo_tcp_unittest.cc
    Line 373, Patchset 11 (Latest): size_t tosend = std::min(static_cast<size_t>(kBlockSize),
    send_buffer_.size() - send_stream_pos_);
    if (tosend > 0) {
    base::span(block).first(tosend).copy_from(base::as_bytes(
    base::span(send_buffer_).subspan(send_stream_pos_, tosend)));
    sent = local_.Send(base::span(block).first(tosend));
    Stephen Nusko . unresolved

    We do this twice? and we never use "tosend" again. Perhaps rename it into a span and use it directly?

    ```suggestion
    auto tosend = base::span(block).first(
    std::min(static_cast<size_t>(kBlockSize),
    send_buffer_.size() - send_stream_pos_));
    if (!tosend.empty()) {
    tosend.copy_from(base::as_bytes(
    base::span(send_buffer_).subspan(send_stream_pos_, tosend.size())));
    sent = local_.Send(tosend);
    ```

    And consider this down below in other spots where it gets reused repeatedly?

    File remoting/protocol/pseudotcp_adapter.cc
    Line 156, Patchset 8: int buffer_size,
    Arthur Sonzogni . unresolved

    Can we `CHECK_EQ(buffer->span().size(), buffer_size)`.

    Eventually, the `buffer_size` argument would be removed, but this is going to take additional refactoring.

    Daniel Angulo

    check_eq is throwing error because buffer->span() and buffer_size are not equal, have just added .first(buffer_size) to the Recv call

    Stephen Nusko

    Are there a lot of calls to it? Can we add the .first() to the callers of Read/Write? As Arthur said eventually we'd like to get rid of these, but if there are a lot of callers this might need to be an eventual cleanup.

    It looks like each PseudoTcpAdapter::Core is only called from one spot, so could we just remove it and move the .first() into the PseudoTcpAdapter::Read/Write? although it also appears they are only called in a couple locations (like 4 files or so each), so we could move the .first() even higher there.

    If you'd like to keep the CL from exploding could we at least add the CHECK arthur requested here, and update PseudoTcpAdapter::Read/Write to call .first() there? And then as a follow up you could propagate it up one level to the 4-8 files.

    Open in Gerrit

    Related details

    Attention is currently required from:
    • Arthur Sonzogni
    • Daniel Angulo
    Submit Requirements:
    • requirement satisfiedCode-Coverage
    • requirement is not satisfiedCode-Owners
    • requirement is not satisfiedCode-Review
    • requirement is not satisfiedNo-Unresolved-Comments
    • requirement is not satisfiedReview-Enforcement
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: comment
    Gerrit-Project: chromium/src
    Gerrit-Branch: main
    Gerrit-Change-Id: Id1a0ff3462edd3d7fa119beff620570f1893a0d8
    Gerrit-Change-Number: 7526157
    Gerrit-PatchSet: 11
    Gerrit-Owner: Daniel Angulo <angd...@google.com>
    Gerrit-Reviewer: Arthur Sonzogni <arthurs...@chromium.org>
    Gerrit-Reviewer: Daniel Angulo <angd...@google.com>
    Gerrit-Reviewer: Stephen Nusko <nus...@chromium.org>
    Gerrit-CC: Code Review Nudger <android-build...@prod.google.com>
    Gerrit-Attention: Daniel Angulo <angd...@google.com>
    Gerrit-Attention: Arthur Sonzogni <arthurs...@chromium.org>
    Gerrit-Comment-Date: Mon, 16 Feb 2026 03:02:24 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    Comment-In-Reply-To: Stephen Nusko <nus...@chromium.org>
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    Arthur Sonzogni (Gerrit)

    unread,
    Feb 16, 2026, 8:36:38 AM (6 days ago) Feb 16
    to Daniel Angulo, Code Review Nudger, Stephen Nusko, AyeAye, Chromium LUCI CQ, chromotin...@chromium.org
    Attention needed from Daniel Angulo

    Arthur Sonzogni added 1 comment

    File remoting/protocol/pseudo_tcp.h
    Line 81, Patchset 9: bool NotifyPacket(base::span<const char> buffer);
    Arthur Sonzogni . unresolved

    Optional: Ma

    Daniel Angulo

    Ma?

    Daniel Angulo

    sorry, what did you say?

    Arthur Sonzogni

    Optional: Maybe this could be `“ase::span<const uint8_t>` directly. This would avoid conversion internally and avoid mixing the two types in this class.

    Of course, that would move the need to convert to the callers, but I think this is better.

    Open in Gerrit

    Related details

    Attention is currently required from:
    • Daniel Angulo
    Submit Requirements:
    • requirement satisfiedCode-Coverage
    • requirement is not satisfiedCode-Owners
    • requirement is not satisfiedCode-Review
    • requirement is not satisfiedNo-Unresolved-Comments
    • requirement is not satisfiedReview-Enforcement
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: comment
    Gerrit-Project: chromium/src
    Gerrit-Branch: main
    Gerrit-Change-Id: Id1a0ff3462edd3d7fa119beff620570f1893a0d8
    Gerrit-Change-Number: 7526157
    Gerrit-PatchSet: 11
    Gerrit-Owner: Daniel Angulo <angd...@google.com>
    Gerrit-Reviewer: Arthur Sonzogni <arthurs...@chromium.org>
    Gerrit-Reviewer: Daniel Angulo <angd...@google.com>
    Gerrit-Reviewer: Stephen Nusko <nus...@chromium.org>
    Gerrit-CC: Code Review Nudger <android-build...@prod.google.com>
    Gerrit-Attention: Daniel Angulo <angd...@google.com>
    Gerrit-Comment-Date: Mon, 16 Feb 2026 13:36:22 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy
    Reply all
    Reply to author
    Forward
    0 new messages