Re: [PATCH] t5500.43: make the check a bit more robust

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Oct 13, 2020 at 02:55:15PM -0400, Jeff King wrote:

> But then in fbd76cd450 (sideband: reverse its dependency on pkt-line,
> 2019-01-16), the function became demultiplex_sideband(). The loop went
> away, and we pump only a single packet on each call. When we see
> sideband 2, we do an early return. But on sideband 1, we continue to the
> cleanup: label, which flushes the scratch buffer.
> 
> I think we need to return from there without hitting that cleanup label,
> like this:

By the way, the reason this works is that the "scratch" buffer persists
beyond individual calls to demultiplex_sideband(). So we can get away
with letting it persist between the two.

However unlike the original recv_sideband(), which broke out of the loop
on error and then flushed scratch, our post-fbd76cd450 does not do the
same. It now looks like:

int recv_sideband(const char *me, int in_stream, int out)
{
        char buf[LARGE_PACKET_MAX + 1];
        int len;
        struct strbuf scratch = STRBUF_INIT;
        enum sideband_type sideband_type;

        while (1) {
                len = packet_read(in_stream, NULL, NULL, buf, LARGE_PACKET_MAX,
                                  0);
                if (!demultiplex_sideband(me, buf, len, 0, &scratch,
                                          &sideband_type))
                        continue;
                switch (sideband_type) {
                case SIDEBAND_PRIMARY:
                        write_or_die(out, buf + 1, len - 1);
                        break;
                default: /* errors: message already written */
                        return sideband_type;
                }
        }
}

I wondered if we could ever have a case where we broke out of the loop
with data left over in "scratch" (or its buffer left allocated). I think
the answer is no. We only break out of the loop if
demultiplex_sideband() returned non-zero _and_ its not the primary
sideband. So both before and after my suggested fix, we'd have hit the
cleanup label in demultiplex_sideband(), which flushes and frees the
buffer.

I do have to say that the original loop before that commit was a lot
easier to follow, though.

Another weirdness I noticed is that it doesn't distinguish a flush
packet (expected) from a zero-byte packet (an error). But neither did
the original. I would have guessed the zero-byte packet was meant to
trigger this second conditional:

        if (len == 0) {
                *sideband_type = SIDEBAND_FLUSH;
                goto cleanup;
        }
        if (len < 1) {
                strbuf_addf(scratch,
                            "%s%s: protocol error: no band designator",
                            scratch->len ? "\n" : "", me);
                *sideband_type = SIDEBAND_PROTOCOL_ERROR;
                goto cleanup;
        }

but we'd hit the first conditional before then. We would still trigger
the second if we saw EOF while reading the packet (because we set the
length to -1 then), but then it's arguably the wrong error to be
showing.

So I think this could be improved a bit by using
packet_read_with_status() in the recv_sideband() caller.

-Peff



[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux