Repository: firecracker-microvm/firecracker
File: src/vmm/src/mmds/mod.rs (Rust)

Code before:
    } else {
        *target = patch.clone();
    }
}

// Make the URI a correct JSON pointer value.
fn sanitize_uri(mut uri: String) -> String {
    let mut len = u32::MAX as usize;
    // Loop while the deduping decreases the sanitized len.
    // Each iteration will attempt to dedup "//".
    while uri.len() < len {
        len = uri.len();
        uri = uri.replace("//", "/");
    }

    uri
}

/// Build a response for `request` and return response based on MMDS version
pub fn convert_to_response(mmds: Arc<Mutex<Mmds>>, request: Request) -> Response {
    let uri = request.uri().get_abs_path();
    if uri.is_empty() {
        return build_response(
            request.http_version(),
            StatusCode::BadRequest,
            None,
            Body::new(VmmMmdsError::InvalidURI.to_string()),
        );
    }

    let mut mmds_guard = mmds.lock().expect("Poisoned lock");

    match mmds_guard.version() {
        MmdsVersion::V1 => respond_to_request_mmdsv1(&mmds_guard, request),
        MmdsVersion::V2 => respond_to_request_mmdsv2(&mut mmds_guard, request),
    }
}

fn respond_to_request_mmdsv1(mmds: &Mmds, request: Request) -> Response {
    // Allow only GET requests.
    match request.method() {
        Method::Get => respond_to_get_request_unchecked(mmds, request),
        _ => {
            let mut response = build_response(
                request.http_version(),
                StatusCode::MethodNotAllowed,
                None,
                Body::new(VmmMmdsError::MethodNotAllowed.to_string()),
            );
            response.allow_method(Method::Get);
            response

Review comment (security):
So, if I'm reading the micro-http code correctly, everytime we pass `None` here, we end up with `application/json`, since that's what `MediaType::default()` returns. In that case, I think all of these error cases should pass `Some(MediaType::PlainText)` here, because the body we construct below is just an unescaped string, e.g. not json, right?

and I guess at that point, we can just make the argument not be an `Option`, as we'll need to pass it almost everywhere anyway

Code after:
    }
}

// Make the URI a correct JSON pointer value.
fn sanitize_uri(mut uri: String) -> String {
    let mut len = u32::MAX as usize;
    // Loop while the deduping decreases the sanitized len.
    // Each iteration will attempt to dedup "//".
    while uri.len() < len {
        len = uri.len();
        uri = uri.replace("//", "/");
    }

    uri
}

/// Build a response for `request` and return response based on MMDS version
pub fn convert_to_response(mmds: Arc<Mutex<Mmds>>, request: Request) -> Response {
    let uri = request.uri().get_abs_path();
    if uri.is_empty() {
        return build_response(
            request.http_version(),
            StatusCode::BadRequest,
            MediaType::PlainText,
            Body::new(VmmMmdsError::InvalidURI.to_string()),
        );
    }

    let mut mmds_guard = mmds.lock().expect("Poisoned lock");

    match mmds_guard.version() {
        MmdsVersion::V1 => respond_to_request_mmdsv1(&mmds_guard, request),
        MmdsVersion::V2 => respond_to_request_mmdsv2(&mut mmds_guard, request),
    }
}

fn respond_to_request_mmdsv1(mmds: &Mmds, request: Request) -> Response {
    // Allow only GET requests.
    match request.method() {
        Method::Get => respond_to_get_request_unchecked(mmds, request),
        _ => {
            let mut response = build_response(
                request.http_version(),
                StatusCode::MethodNotAllowed,
                MediaType::PlainText,
                Body::new(VmmMmdsError::MethodNotAllowed.to_string()),
            );
            response.allow_method(Method::Get);
            response
        }
    }