Skip to content

buffer: bound = 0 panics in Buffer::new / Buffer::pair (and via BufferLayer::new) #861

@meng-xu-cs

Description

@meng-xu-cs

Summary

Buffer::new, Buffer::pair, and BufferLayer::new accept bound: usize, but 0 is not actually supported. Buffer::pair forwards bound directly to tokio::sync::mpsc::channel(bound), which panics when the capacity is 0.

Because the public Tower docs describe bound as the maximum number of queued requests before backpressure, but do not document 0 as invalid, this currently turns an apparently-valid configuration into an immediate panic.

Reproduction

use std::{
    convert::Infallible,
    future::{ready, Ready},
    task::{Context, Poll},
};
use tower::{buffer::Buffer, Service};

#[derive(Clone)]
struct Svc;

impl Service<()> for Svc {
    type Response = ();
    type Error = Infallible;
    type Future = Ready<Result<(), Infallible>>;

    fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
        Poll::Ready(Ok(()))
    }

    fn call(&mut self, _req: ()) -> Self::Future {
        ready(Ok(()))
    }
}

fn main() {
    let _ = Buffer::pair(Svc, 0);
}

This can crash applications during startup or reconfiguration when the buffer size is computed dynamically or loaded from configuration and reaches zero. But in practice, the chance that this can cause any denial-of-service (DoS) attack is almost zero, so it is not a security concern, more like a surprise.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions