From 3c8b130be89fbb0e58e2ee23f07ad56a3b9de2e7 Mon Sep 17 00:00:00 2001 From: Andrew Guschin Date: Fri, 30 Oct 2026 05:15:56 +0400 Subject: Reject streamed diagnostic error documents and record VM qualification --- src/diagnostics.rs | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) (limited to 'src/diagnostics.rs') diff --git a/src/diagnostics.rs b/src/diagnostics.rs index f6ed82a..d8f8620 100644 --- a/src/diagnostics.rs +++ b/src/diagnostics.rs @@ -1,3 +1,5 @@ +mod error_document; + use crate::model::Settings; use anyhow::{Result, anyhow, ensure}; use futures_util::TryStreamExt; @@ -113,6 +115,7 @@ pub async fn measure( let mut reader = tokio_util::io::StreamReader::new(stream); let mut buffer = [0u8; 16384]; let mut prefix = Vec::new(); + let mut error_document = error_document::ErrorDocument::default(); let mut bytes = 0; let reason; loop { @@ -144,8 +147,23 @@ pub async fn measure( break; } if prefix.len() < 512 { - prefix.extend_from_slice(&buffer[..chunk.min(512 - prefix.len())]); + let mut inspect = &buffer[..chunk]; + if prefix.is_empty() { + inspect = inspect.trim_ascii_start(); + while inspect + .first() + .is_some_and(|byte| matches!(byte, 0xef | 0xbb | 0xbf)) + { + inspect = inspect[1..].trim_ascii_start(); + } + } + prefix.extend_from_slice(&inspect[..inspect.len().min(512 - prefix.len())]); } + error_document.feed(&buffer[..chunk]); + ensure!( + !error_document.confirmed_error(), + "Diagnostic endpoint returned an error document" + ); bytes += chunk as u64; if !speed { ensure!(bytes <= cap, "Ping body exceeds 4 KiB"); @@ -158,17 +176,8 @@ pub async fn measure( !prefix.starts_with("(&prefix) - .ok() - .is_some_and(|body| { - ["error", "errors"].iter().any(|key| { - body.get(key).is_some_and(|value| { - !value.is_null() && value != false && value != 0 && value != "" - }) - }) - }); ensure!( - !json_error, + !error_document.is_error(), "Diagnostic endpoint returned an error document" ); ensure!(!speed || bytes > 0, "Speed response contained no data"); -- cgit v1.2.3