bitreq: Add RFC 9112 compliance test vectors - #660

Closed
tnull wants to merge 3 commits into
rust-bitcoin:masterfrom
tnull:2026-07-spec-compliance
Closed

bitreq: Add RFC 9112 compliance test vectors#660
tnull wants to merge 3 commits into
rust-bitcoin:masterfrom
tnull:2026-07-spec-compliance

Conversation

@tnull

Copy link
Copy Markdown
Collaborator

In #659 we recently discovered that we aren't fully compliant with RFC 9112 / HTTP 1.1.

As a first step of mitigation, we here add some test vectors that cover the central points. We opted to mark the (33!) failing checks as ignored, so we can revisit and fix them in following PRs (instead of cramming everything into one PR).

  • Response/cache poisoning: Extra unsolicited bytes can be accepted as the next response (§§6.3, 9.2).
  • Request smuggling/injection: Custom methods and headers allow CR/control-character injection; conflicting Host fields are transmitted (§§2.2–5).
  • Ambiguous message framing: Requests can contain both Content-Length and Transfer-Encoding; conflicting response lengths are accepted (§§6.1–6.3).
  • Incomplete responses accepted: Premature EOF, missing terminal zero chunks, and truncated header sections can be treated as complete (§8).
  • Invalid response syntax accepted: Malformed status lines, bare CR, whitespace-prefixed fields, and obsolete line folding are not handled as required (§§2–5).
  • Incorrect transfer-coding handling: Coding lists such as gzip, chunked, HTTP/1.0 Transfer-Encoding, and trailers are mishandled (§§6–7).
  • Broken connection semantics: HTTP/1.1 persistence incorrectly requires keep-alive; sent Connection: close can be ignored; tokenized options are not parsed correctly (§§9.3, 9.6).
  • CONNECT noncompliance: CONNECT uses the wrong request-target, omits the required proxy Host, and treats successful CONNECT responses as ordinary bodies (§§3.2, 6.3).

And more minor:

  • Consume 1xx informational responses until the final response.
  • Treat clean async EOF as successful for valid close-delimited responses.
  • Retry unanswered pipelined requests without immediately re-pipelining.

tnull added 3 commits July 11, 2026 15:21
Exercise the HTTP/1.1 wire grammar so request generation and
response parsing gaps are visible before behavior is changed.
Co-Authored-By: HAL 9000
Cover response length and chunk decoding rules so incomplete or
ambiguous messages cannot pass unnoticed.
Co-Authored-By: HAL 9000
Cover persistence, closure, and pipelining rules so connection
reuse can be corrected against explicit expectations.
Refs: rust-bitcoin#659
Co-Authored-By: HAL 9000

@TheBlueMattTheBlueMatt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks!

}

#[test]
#[ignore = "TODO: reject bare CR in request protocol elements (RFC 9112 Section 2.2)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we actually intend to fix all these? I'm happy to see them fixed if we care, but its not clear to me that we do/should, at which point adding tests for them is just noise.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think we should. #661 is the start, but I intend to tackle these bit-by-bit in follow-ups.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW I don't think we should bother trying to be super strict on what the calling code passes. In this case specifically where the request is invalid, I think we should just accept it. The only exception would be if the request is bad in a way that will break our request code, ie if it might make two requests because it adds a \r\n\r\nGET... or something similar. I think that basically just means rejecting \r\ns and maybe rejecting standalone \r and \ns

@tnull
tnull requested a review from TheBlueMattJuly 20, 2026 07:51

@TheBlueMattTheBlueMatt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I skimmed about the first half of these. I think most of them its not worth enforcing - stuff where the server or client are maybe a bit confused but we can parse the resulting stream fine I really don't think we should add code to be strict on the RFC for.

}

#[test]
#[ignore = "TODO: reject bare CR in request protocol elements (RFC 9112 Section 2.2)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW I don't think we should bother trying to be super strict on what the calling code passes. In this case specifically where the request is invalid, I think we should just accept it. The only exception would be if the request is bad in a way that will break our request code, ie if it might make two requests because it adds a \r\n\r\nGET... or something similar. I think that basically just means rejecting \r\ns and maybe rejecting standalone \r and \ns

}

#[test]
#[ignore = "TODO: reject invalid request field names (RFC 9112 Sections 2.2 and 5)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should bother rejecting this.

}

#[test]
#[ignore = "TODO: reject conflicting Host fields (RFC 9112 Section 3.2)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should worry about stuff like this.


#[test]
#[ignore = "TODO: validate response status-line grammar (RFC 9112 Sections 2.3 and 4)"]
fn section_4_invalid_status_lines_are_rejected() {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should enforce this.

}

#[test]
#[ignore = "TODO: reject or ignore whitespace-prefixed fields (RFC 9112 Section 2.2)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see why we should enforce this.

#[test]
#[ignore = "TODO: reject repeated chunked transfer coding (RFC 9112 Section 6.1)"]
fn section_6_1_sender_rejects_repeated_chunked_coding() {
// RFC 9112 Section 6.1: a sender MUST NOT apply chunked transfer coding more than once.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see why we should reject this.

}

#[test]
#[ignore = "TODO: exclude chunked from TE requests (RFC 9112 Section 7.4)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's please not add parsing of random client headers just to enforce them.

}

#[test]
#[ignore = "TODO: add the TE connection option when sending TE (RFC 9112 Section 7.4)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

#[ignore = "TODO: treat successful CONNECT responses as tunnels (RFC 9112 Section 6.3)"]
fn section_6_3_successful_connect_ignores_framing_fields() {
// RFC 9112 Section 6.3: a client receiving a successful CONNECT response MUST ignore
// Content-Length and Transfer-Encoding because the connection becomes a tunnel.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we even going to support parsing this? Its not clear how to parse this if we're pipelining and if a proxy is this broken kinda who cares?

#[ignore = "TODO: reject Transfer-Encoding in HTTP/1.0 responses (RFC 9112 Section 6.1)"]
fn section_6_1_http_1_0_transfer_encoding_is_faulty() {
// RFC 9112 Section 6.1: a client receiving Transfer-Encoding in HTTP/1.0 MUST treat framing as
// faulty and close the connection.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is it worth our time to enforce this?

@tcharding

tcharding commented Jul 23, 2026

Copy link
Copy Markdown
Member

Please note development has migrated to https://git.rust-bitcoin.org/rust-bitcoin/corepc. Any further comments or pushes here on github may be ignored or lost. Closing since I know @tnull is ok with the migration.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@tnull@tcharding@TheBlueMatt
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

bitreq: Add RFC 9112 compliance test vectors - #660

Closed
tnull wants to merge 3 commits into
rust-bitcoin:masterfrom
tnull:2026-07-spec-compliance
Closed

bitreq: Add RFC 9112 compliance test vectors#660
tnull wants to merge 3 commits into
rust-bitcoin:masterfrom
tnull:2026-07-spec-compliance

Conversation

@tnull

Copy link
Copy Markdown
Collaborator

In #659 we recently discovered that we aren't fully compliant with RFC 9112 / HTTP 1.1.

As a first step of mitigation, we here add some test vectors that cover the central points. We opted to mark the (33!) failing checks as ignored, so we can revisit and fix them in following PRs (instead of cramming everything into one PR).

  • Response/cache poisoning: Extra unsolicited bytes can be accepted as the next response (§§6.3, 9.2).
  • Request smuggling/injection: Custom methods and headers allow CR/control-character injection; conflicting Host fields are transmitted (§§2.2–5).
  • Ambiguous message framing: Requests can contain both Content-Length and Transfer-Encoding; conflicting response lengths are accepted (§§6.1–6.3).
  • Incomplete responses accepted: Premature EOF, missing terminal zero chunks, and truncated header sections can be treated as complete (§8).
  • Invalid response syntax accepted: Malformed status lines, bare CR, whitespace-prefixed fields, and obsolete line folding are not handled as required (§§2–5).
  • Incorrect transfer-coding handling: Coding lists such as gzip, chunked, HTTP/1.0 Transfer-Encoding, and trailers are mishandled (§§6–7).
  • Broken connection semantics: HTTP/1.1 persistence incorrectly requires keep-alive; sent Connection: close can be ignored; tokenized options are not parsed correctly (§§9.3, 9.6).
  • CONNECT noncompliance: CONNECT uses the wrong request-target, omits the required proxy Host, and treats successful CONNECT responses as ordinary bodies (§§3.2, 6.3).

And more minor:

  • Consume 1xx informational responses until the final response.
  • Treat clean async EOF as successful for valid close-delimited responses.
  • Retry unanswered pipelined requests without immediately re-pipelining.

tnull added 3 commits July 11, 2026 15:21
Exercise the HTTP/1.1 wire grammar so request generation and
response parsing gaps are visible before behavior is changed.
Co-Authored-By: HAL 9000
Cover response length and chunk decoding rules so incomplete or
ambiguous messages cannot pass unnoticed.
Co-Authored-By: HAL 9000
Cover persistence, closure, and pipelining rules so connection
reuse can be corrected against explicit expectations.
Refs: rust-bitcoin#659
Co-Authored-By: HAL 9000

@TheBlueMattTheBlueMatt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks!

}

#[test]
#[ignore = "TODO: reject bare CR in request protocol elements (RFC 9112 Section 2.2)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we actually intend to fix all these? I'm happy to see them fixed if we care, but its not clear to me that we do/should, at which point adding tests for them is just noise.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think we should. #661 is the start, but I intend to tackle these bit-by-bit in follow-ups.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW I don't think we should bother trying to be super strict on what the calling code passes. In this case specifically where the request is invalid, I think we should just accept it. The only exception would be if the request is bad in a way that will break our request code, ie if it might make two requests because it adds a \r\n\r\nGET... or something similar. I think that basically just means rejecting \r\ns and maybe rejecting standalone \r and \ns

@tnull
tnull requested a review from TheBlueMattJuly 20, 2026 07:51

@TheBlueMattTheBlueMatt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I skimmed about the first half of these. I think most of them its not worth enforcing - stuff where the server or client are maybe a bit confused but we can parse the resulting stream fine I really don't think we should add code to be strict on the RFC for.

}

#[test]
#[ignore = "TODO: reject bare CR in request protocol elements (RFC 9112 Section 2.2)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW I don't think we should bother trying to be super strict on what the calling code passes. In this case specifically where the request is invalid, I think we should just accept it. The only exception would be if the request is bad in a way that will break our request code, ie if it might make two requests because it adds a \r\n\r\nGET... or something similar. I think that basically just means rejecting \r\ns and maybe rejecting standalone \r and \ns

}

#[test]
#[ignore = "TODO: reject invalid request field names (RFC 9112 Sections 2.2 and 5)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should bother rejecting this.

}

#[test]
#[ignore = "TODO: reject conflicting Host fields (RFC 9112 Section 3.2)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should worry about stuff like this.


#[test]
#[ignore = "TODO: validate response status-line grammar (RFC 9112 Sections 2.3 and 4)"]
fn section_4_invalid_status_lines_are_rejected() {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should enforce this.

}

#[test]
#[ignore = "TODO: reject or ignore whitespace-prefixed fields (RFC 9112 Section 2.2)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see why we should enforce this.

#[test]
#[ignore = "TODO: reject repeated chunked transfer coding (RFC 9112 Section 6.1)"]
fn section_6_1_sender_rejects_repeated_chunked_coding() {
// RFC 9112 Section 6.1: a sender MUST NOT apply chunked transfer coding more than once.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see why we should reject this.

}

#[test]
#[ignore = "TODO: exclude chunked from TE requests (RFC 9112 Section 7.4)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's please not add parsing of random client headers just to enforce them.

}

#[test]
#[ignore = "TODO: add the TE connection option when sending TE (RFC 9112 Section 7.4)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

#[ignore = "TODO: treat successful CONNECT responses as tunnels (RFC 9112 Section 6.3)"]
fn section_6_3_successful_connect_ignores_framing_fields() {
// RFC 9112 Section 6.3: a client receiving a successful CONNECT response MUST ignore
// Content-Length and Transfer-Encoding because the connection becomes a tunnel.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we even going to support parsing this? Its not clear how to parse this if we're pipelining and if a proxy is this broken kinda who cares?

#[ignore = "TODO: reject Transfer-Encoding in HTTP/1.0 responses (RFC 9112 Section 6.1)"]
fn section_6_1_http_1_0_transfer_encoding_is_faulty() {
// RFC 9112 Section 6.1: a client receiving Transfer-Encoding in HTTP/1.0 MUST treat framing as
// faulty and close the connection.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is it worth our time to enforce this?

@tcharding

tcharding commented Jul 23, 2026

Copy link
Copy Markdown
Member

Please note development has migrated to https://git.rust-bitcoin.org/rust-bitcoin/corepc. Any further comments or pushes here on github may be ignored or lost. Closing since I know @tnull is ok with the migration.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@tnull@tcharding@TheBlueMatt
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

bitreq: Add RFC 9112 compliance test vectors - #660

Closed
tnull wants to merge 3 commits into
rust-bitcoin:masterfrom
tnull:2026-07-spec-compliance
Closed

bitreq: Add RFC 9112 compliance test vectors#660
tnull wants to merge 3 commits into
rust-bitcoin:masterfrom
tnull:2026-07-spec-compliance

Conversation

@tnull

Copy link
Copy Markdown
Collaborator

In #659 we recently discovered that we aren't fully compliant with RFC 9112 / HTTP 1.1.

As a first step of mitigation, we here add some test vectors that cover the central points. We opted to mark the (33!) failing checks as ignored, so we can revisit and fix them in following PRs (instead of cramming everything into one PR).

  • Response/cache poisoning: Extra unsolicited bytes can be accepted as the next response (§§6.3, 9.2).
  • Request smuggling/injection: Custom methods and headers allow CR/control-character injection; conflicting Host fields are transmitted (§§2.2–5).
  • Ambiguous message framing: Requests can contain both Content-Length and Transfer-Encoding; conflicting response lengths are accepted (§§6.1–6.3).
  • Incomplete responses accepted: Premature EOF, missing terminal zero chunks, and truncated header sections can be treated as complete (§8).
  • Invalid response syntax accepted: Malformed status lines, bare CR, whitespace-prefixed fields, and obsolete line folding are not handled as required (§§2–5).
  • Incorrect transfer-coding handling: Coding lists such as gzip, chunked, HTTP/1.0 Transfer-Encoding, and trailers are mishandled (§§6–7).
  • Broken connection semantics: HTTP/1.1 persistence incorrectly requires keep-alive; sent Connection: close can be ignored; tokenized options are not parsed correctly (§§9.3, 9.6).
  • CONNECT noncompliance: CONNECT uses the wrong request-target, omits the required proxy Host, and treats successful CONNECT responses as ordinary bodies (§§3.2, 6.3).

And more minor:

  • Consume 1xx informational responses until the final response.
  • Treat clean async EOF as successful for valid close-delimited responses.
  • Retry unanswered pipelined requests without immediately re-pipelining.

tnull added 3 commits July 11, 2026 15:21
Exercise the HTTP/1.1 wire grammar so request generation and
response parsing gaps are visible before behavior is changed.
Co-Authored-By: HAL 9000
Cover response length and chunk decoding rules so incomplete or
ambiguous messages cannot pass unnoticed.
Co-Authored-By: HAL 9000
Cover persistence, closure, and pipelining rules so connection
reuse can be corrected against explicit expectations.
Refs: rust-bitcoin#659
Co-Authored-By: HAL 9000

@TheBlueMattTheBlueMatt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks!

}

#[test]
#[ignore = "TODO: reject bare CR in request protocol elements (RFC 9112 Section 2.2)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we actually intend to fix all these? I'm happy to see them fixed if we care, but its not clear to me that we do/should, at which point adding tests for them is just noise.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think we should. #661 is the start, but I intend to tackle these bit-by-bit in follow-ups.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW I don't think we should bother trying to be super strict on what the calling code passes. In this case specifically where the request is invalid, I think we should just accept it. The only exception would be if the request is bad in a way that will break our request code, ie if it might make two requests because it adds a \r\n\r\nGET... or something similar. I think that basically just means rejecting \r\ns and maybe rejecting standalone \r and \ns

@tnull
tnull requested a review from TheBlueMattJuly 20, 2026 07:51

@TheBlueMattTheBlueMatt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I skimmed about the first half of these. I think most of them its not worth enforcing - stuff where the server or client are maybe a bit confused but we can parse the resulting stream fine I really don't think we should add code to be strict on the RFC for.

}

#[test]
#[ignore = "TODO: reject bare CR in request protocol elements (RFC 9112 Section 2.2)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW I don't think we should bother trying to be super strict on what the calling code passes. In this case specifically where the request is invalid, I think we should just accept it. The only exception would be if the request is bad in a way that will break our request code, ie if it might make two requests because it adds a \r\n\r\nGET... or something similar. I think that basically just means rejecting \r\ns and maybe rejecting standalone \r and \ns

}

#[test]
#[ignore = "TODO: reject invalid request field names (RFC 9112 Sections 2.2 and 5)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should bother rejecting this.

}

#[test]
#[ignore = "TODO: reject conflicting Host fields (RFC 9112 Section 3.2)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should worry about stuff like this.


#[test]
#[ignore = "TODO: validate response status-line grammar (RFC 9112 Sections 2.3 and 4)"]
fn section_4_invalid_status_lines_are_rejected() {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should enforce this.

}

#[test]
#[ignore = "TODO: reject or ignore whitespace-prefixed fields (RFC 9112 Section 2.2)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see why we should enforce this.

#[test]
#[ignore = "TODO: reject repeated chunked transfer coding (RFC 9112 Section 6.1)"]
fn section_6_1_sender_rejects_repeated_chunked_coding() {
// RFC 9112 Section 6.1: a sender MUST NOT apply chunked transfer coding more than once.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see why we should reject this.

}

#[test]
#[ignore = "TODO: exclude chunked from TE requests (RFC 9112 Section 7.4)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's please not add parsing of random client headers just to enforce them.

}

#[test]
#[ignore = "TODO: add the TE connection option when sending TE (RFC 9112 Section 7.4)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

#[ignore = "TODO: treat successful CONNECT responses as tunnels (RFC 9112 Section 6.3)"]
fn section_6_3_successful_connect_ignores_framing_fields() {
// RFC 9112 Section 6.3: a client receiving a successful CONNECT response MUST ignore
// Content-Length and Transfer-Encoding because the connection becomes a tunnel.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we even going to support parsing this? Its not clear how to parse this if we're pipelining and if a proxy is this broken kinda who cares?

#[ignore = "TODO: reject Transfer-Encoding in HTTP/1.0 responses (RFC 9112 Section 6.1)"]
fn section_6_1_http_1_0_transfer_encoding_is_faulty() {
// RFC 9112 Section 6.1: a client receiving Transfer-Encoding in HTTP/1.0 MUST treat framing as
// faulty and close the connection.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is it worth our time to enforce this?

@tcharding

tcharding commented Jul 23, 2026

Copy link
Copy Markdown
Member

Please note development has migrated to https://git.rust-bitcoin.org/rust-bitcoin/corepc. Any further comments or pushes here on github may be ignored or lost. Closing since I know @tnull is ok with the migration.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@tnull@tcharding@TheBlueMatt
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

bitreq: Add RFC 9112 compliance test vectors - #660

Closed
tnull wants to merge 3 commits into
rust-bitcoin:masterfrom
tnull:2026-07-spec-compliance
Closed

bitreq: Add RFC 9112 compliance test vectors#660
tnull wants to merge 3 commits into
rust-bitcoin:masterfrom
tnull:2026-07-spec-compliance

Conversation

@tnull

Copy link
Copy Markdown
Collaborator

In #659 we recently discovered that we aren't fully compliant with RFC 9112 / HTTP 1.1.

As a first step of mitigation, we here add some test vectors that cover the central points. We opted to mark the (33!) failing checks as ignored, so we can revisit and fix them in following PRs (instead of cramming everything into one PR).

  • Response/cache poisoning: Extra unsolicited bytes can be accepted as the next response (§§6.3, 9.2).
  • Request smuggling/injection: Custom methods and headers allow CR/control-character injection; conflicting Host fields are transmitted (§§2.2–5).
  • Ambiguous message framing: Requests can contain both Content-Length and Transfer-Encoding; conflicting response lengths are accepted (§§6.1–6.3).
  • Incomplete responses accepted: Premature EOF, missing terminal zero chunks, and truncated header sections can be treated as complete (§8).
  • Invalid response syntax accepted: Malformed status lines, bare CR, whitespace-prefixed fields, and obsolete line folding are not handled as required (§§2–5).
  • Incorrect transfer-coding handling: Coding lists such as gzip, chunked, HTTP/1.0 Transfer-Encoding, and trailers are mishandled (§§6–7).
  • Broken connection semantics: HTTP/1.1 persistence incorrectly requires keep-alive; sent Connection: close can be ignored; tokenized options are not parsed correctly (§§9.3, 9.6).
  • CONNECT noncompliance: CONNECT uses the wrong request-target, omits the required proxy Host, and treats successful CONNECT responses as ordinary bodies (§§3.2, 6.3).

And more minor:

  • Consume 1xx informational responses until the final response.
  • Treat clean async EOF as successful for valid close-delimited responses.
  • Retry unanswered pipelined requests without immediately re-pipelining.

tnull added 3 commits July 11, 2026 15:21
Exercise the HTTP/1.1 wire grammar so request generation and
response parsing gaps are visible before behavior is changed.
Co-Authored-By: HAL 9000
Cover response length and chunk decoding rules so incomplete or
ambiguous messages cannot pass unnoticed.
Co-Authored-By: HAL 9000
Cover persistence, closure, and pipelining rules so connection
reuse can be corrected against explicit expectations.
Refs: rust-bitcoin#659
Co-Authored-By: HAL 9000

@TheBlueMattTheBlueMatt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks!

}

#[test]
#[ignore = "TODO: reject bare CR in request protocol elements (RFC 9112 Section 2.2)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we actually intend to fix all these? I'm happy to see them fixed if we care, but its not clear to me that we do/should, at which point adding tests for them is just noise.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think we should. #661 is the start, but I intend to tackle these bit-by-bit in follow-ups.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW I don't think we should bother trying to be super strict on what the calling code passes. In this case specifically where the request is invalid, I think we should just accept it. The only exception would be if the request is bad in a way that will break our request code, ie if it might make two requests because it adds a \r\n\r\nGET... or something similar. I think that basically just means rejecting \r\ns and maybe rejecting standalone \r and \ns

@tnull
tnull requested a review from TheBlueMattJuly 20, 2026 07:51

@TheBlueMattTheBlueMatt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I skimmed about the first half of these. I think most of them its not worth enforcing - stuff where the server or client are maybe a bit confused but we can parse the resulting stream fine I really don't think we should add code to be strict on the RFC for.

}

#[test]
#[ignore = "TODO: reject bare CR in request protocol elements (RFC 9112 Section 2.2)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW I don't think we should bother trying to be super strict on what the calling code passes. In this case specifically where the request is invalid, I think we should just accept it. The only exception would be if the request is bad in a way that will break our request code, ie if it might make two requests because it adds a \r\n\r\nGET... or something similar. I think that basically just means rejecting \r\ns and maybe rejecting standalone \r and \ns

}

#[test]
#[ignore = "TODO: reject invalid request field names (RFC 9112 Sections 2.2 and 5)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should bother rejecting this.

}

#[test]
#[ignore = "TODO: reject conflicting Host fields (RFC 9112 Section 3.2)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should worry about stuff like this.


#[test]
#[ignore = "TODO: validate response status-line grammar (RFC 9112 Sections 2.3 and 4)"]
fn section_4_invalid_status_lines_are_rejected() {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should enforce this.

}

#[test]
#[ignore = "TODO: reject or ignore whitespace-prefixed fields (RFC 9112 Section 2.2)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see why we should enforce this.

#[test]
#[ignore = "TODO: reject repeated chunked transfer coding (RFC 9112 Section 6.1)"]
fn section_6_1_sender_rejects_repeated_chunked_coding() {
// RFC 9112 Section 6.1: a sender MUST NOT apply chunked transfer coding more than once.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see why we should reject this.

}

#[test]
#[ignore = "TODO: exclude chunked from TE requests (RFC 9112 Section 7.4)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's please not add parsing of random client headers just to enforce them.

}

#[test]
#[ignore = "TODO: add the TE connection option when sending TE (RFC 9112 Section 7.4)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

#[ignore = "TODO: treat successful CONNECT responses as tunnels (RFC 9112 Section 6.3)"]
fn section_6_3_successful_connect_ignores_framing_fields() {
// RFC 9112 Section 6.3: a client receiving a successful CONNECT response MUST ignore
// Content-Length and Transfer-Encoding because the connection becomes a tunnel.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we even going to support parsing this? Its not clear how to parse this if we're pipelining and if a proxy is this broken kinda who cares?

#[ignore = "TODO: reject Transfer-Encoding in HTTP/1.0 responses (RFC 9112 Section 6.1)"]
fn section_6_1_http_1_0_transfer_encoding_is_faulty() {
// RFC 9112 Section 6.1: a client receiving Transfer-Encoding in HTTP/1.0 MUST treat framing as
// faulty and close the connection.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is it worth our time to enforce this?

@tcharding

tcharding commented Jul 23, 2026

Copy link
Copy Markdown
Member

Please note development has migrated to https://git.rust-bitcoin.org/rust-bitcoin/corepc. Any further comments or pushes here on github may be ignored or lost. Closing since I know @tnull is ok with the migration.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@tnull@tcharding@TheBlueMatt
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

bitreq: Add RFC 9112 compliance test vectors - #660

Closed
tnull wants to merge 3 commits into
rust-bitcoin:masterfrom
tnull:2026-07-spec-compliance
Closed

bitreq: Add RFC 9112 compliance test vectors#660
tnull wants to merge 3 commits into
rust-bitcoin:masterfrom
tnull:2026-07-spec-compliance

Conversation

@tnull

Copy link
Copy Markdown
Collaborator

In #659 we recently discovered that we aren't fully compliant with RFC 9112 / HTTP 1.1.

As a first step of mitigation, we here add some test vectors that cover the central points. We opted to mark the (33!) failing checks as ignored, so we can revisit and fix them in following PRs (instead of cramming everything into one PR).

  • Response/cache poisoning: Extra unsolicited bytes can be accepted as the next response (§§6.3, 9.2).
  • Request smuggling/injection: Custom methods and headers allow CR/control-character injection; conflicting Host fields are transmitted (§§2.2–5).
  • Ambiguous message framing: Requests can contain both Content-Length and Transfer-Encoding; conflicting response lengths are accepted (§§6.1–6.3).
  • Incomplete responses accepted: Premature EOF, missing terminal zero chunks, and truncated header sections can be treated as complete (§8).
  • Invalid response syntax accepted: Malformed status lines, bare CR, whitespace-prefixed fields, and obsolete line folding are not handled as required (§§2–5).
  • Incorrect transfer-coding handling: Coding lists such as gzip, chunked, HTTP/1.0 Transfer-Encoding, and trailers are mishandled (§§6–7).
  • Broken connection semantics: HTTP/1.1 persistence incorrectly requires keep-alive; sent Connection: close can be ignored; tokenized options are not parsed correctly (§§9.3, 9.6).
  • CONNECT noncompliance: CONNECT uses the wrong request-target, omits the required proxy Host, and treats successful CONNECT responses as ordinary bodies (§§3.2, 6.3).

And more minor:

  • Consume 1xx informational responses until the final response.
  • Treat clean async EOF as successful for valid close-delimited responses.
  • Retry unanswered pipelined requests without immediately re-pipelining.

tnull added 3 commits July 11, 2026 15:21
Exercise the HTTP/1.1 wire grammar so request generation and
response parsing gaps are visible before behavior is changed.
Co-Authored-By: HAL 9000
Cover response length and chunk decoding rules so incomplete or
ambiguous messages cannot pass unnoticed.
Co-Authored-By: HAL 9000
Cover persistence, closure, and pipelining rules so connection
reuse can be corrected against explicit expectations.
Refs: rust-bitcoin#659
Co-Authored-By: HAL 9000

@TheBlueMattTheBlueMatt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks!

}

#[test]
#[ignore = "TODO: reject bare CR in request protocol elements (RFC 9112 Section 2.2)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we actually intend to fix all these? I'm happy to see them fixed if we care, but its not clear to me that we do/should, at which point adding tests for them is just noise.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think we should. #661 is the start, but I intend to tackle these bit-by-bit in follow-ups.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW I don't think we should bother trying to be super strict on what the calling code passes. In this case specifically where the request is invalid, I think we should just accept it. The only exception would be if the request is bad in a way that will break our request code, ie if it might make two requests because it adds a \r\n\r\nGET... or something similar. I think that basically just means rejecting \r\ns and maybe rejecting standalone \r and \ns

@tnull
tnull requested a review from TheBlueMattJuly 20, 2026 07:51

@TheBlueMattTheBlueMatt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I skimmed about the first half of these. I think most of them its not worth enforcing - stuff where the server or client are maybe a bit confused but we can parse the resulting stream fine I really don't think we should add code to be strict on the RFC for.

}

#[test]
#[ignore = "TODO: reject bare CR in request protocol elements (RFC 9112 Section 2.2)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW I don't think we should bother trying to be super strict on what the calling code passes. In this case specifically where the request is invalid, I think we should just accept it. The only exception would be if the request is bad in a way that will break our request code, ie if it might make two requests because it adds a \r\n\r\nGET... or something similar. I think that basically just means rejecting \r\ns and maybe rejecting standalone \r and \ns

}

#[test]
#[ignore = "TODO: reject invalid request field names (RFC 9112 Sections 2.2 and 5)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should bother rejecting this.

}

#[test]
#[ignore = "TODO: reject conflicting Host fields (RFC 9112 Section 3.2)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should worry about stuff like this.


#[test]
#[ignore = "TODO: validate response status-line grammar (RFC 9112 Sections 2.3 and 4)"]
fn section_4_invalid_status_lines_are_rejected() {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should enforce this.

}

#[test]
#[ignore = "TODO: reject or ignore whitespace-prefixed fields (RFC 9112 Section 2.2)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see why we should enforce this.

#[test]
#[ignore = "TODO: reject repeated chunked transfer coding (RFC 9112 Section 6.1)"]
fn section_6_1_sender_rejects_repeated_chunked_coding() {
// RFC 9112 Section 6.1: a sender MUST NOT apply chunked transfer coding more than once.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see why we should reject this.

}

#[test]
#[ignore = "TODO: exclude chunked from TE requests (RFC 9112 Section 7.4)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's please not add parsing of random client headers just to enforce them.

}

#[test]
#[ignore = "TODO: add the TE connection option when sending TE (RFC 9112 Section 7.4)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

#[ignore = "TODO: treat successful CONNECT responses as tunnels (RFC 9112 Section 6.3)"]
fn section_6_3_successful_connect_ignores_framing_fields() {
// RFC 9112 Section 6.3: a client receiving a successful CONNECT response MUST ignore
// Content-Length and Transfer-Encoding because the connection becomes a tunnel.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we even going to support parsing this? Its not clear how to parse this if we're pipelining and if a proxy is this broken kinda who cares?

#[ignore = "TODO: reject Transfer-Encoding in HTTP/1.0 responses (RFC 9112 Section 6.1)"]
fn section_6_1_http_1_0_transfer_encoding_is_faulty() {
// RFC 9112 Section 6.1: a client receiving Transfer-Encoding in HTTP/1.0 MUST treat framing as
// faulty and close the connection.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is it worth our time to enforce this?

@tcharding

tcharding commented Jul 23, 2026

Copy link
Copy Markdown
Member

Please note development has migrated to https://git.rust-bitcoin.org/rust-bitcoin/corepc. Any further comments or pushes here on github may be ignored or lost. Closing since I know @tnull is ok with the migration.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@tnull@tcharding@TheBlueMatt
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

bitreq: Add RFC 9112 compliance test vectors - #660

Closed
tnull wants to merge 3 commits into
rust-bitcoin:masterfrom
tnull:2026-07-spec-compliance
Closed

bitreq: Add RFC 9112 compliance test vectors#660
tnull wants to merge 3 commits into
rust-bitcoin:masterfrom
tnull:2026-07-spec-compliance

Conversation

@tnull

Copy link
Copy Markdown
Collaborator

In #659 we recently discovered that we aren't fully compliant with RFC 9112 / HTTP 1.1.

As a first step of mitigation, we here add some test vectors that cover the central points. We opted to mark the (33!) failing checks as ignored, so we can revisit and fix them in following PRs (instead of cramming everything into one PR).

  • Response/cache poisoning: Extra unsolicited bytes can be accepted as the next response (§§6.3, 9.2).
  • Request smuggling/injection: Custom methods and headers allow CR/control-character injection; conflicting Host fields are transmitted (§§2.2–5).
  • Ambiguous message framing: Requests can contain both Content-Length and Transfer-Encoding; conflicting response lengths are accepted (§§6.1–6.3).
  • Incomplete responses accepted: Premature EOF, missing terminal zero chunks, and truncated header sections can be treated as complete (§8).
  • Invalid response syntax accepted: Malformed status lines, bare CR, whitespace-prefixed fields, and obsolete line folding are not handled as required (§§2–5).
  • Incorrect transfer-coding handling: Coding lists such as gzip, chunked, HTTP/1.0 Transfer-Encoding, and trailers are mishandled (§§6–7).
  • Broken connection semantics: HTTP/1.1 persistence incorrectly requires keep-alive; sent Connection: close can be ignored; tokenized options are not parsed correctly (§§9.3, 9.6).
  • CONNECT noncompliance: CONNECT uses the wrong request-target, omits the required proxy Host, and treats successful CONNECT responses as ordinary bodies (§§3.2, 6.3).

And more minor:

  • Consume 1xx informational responses until the final response.
  • Treat clean async EOF as successful for valid close-delimited responses.
  • Retry unanswered pipelined requests without immediately re-pipelining.

tnull added 3 commits July 11, 2026 15:21
Exercise the HTTP/1.1 wire grammar so request generation and
response parsing gaps are visible before behavior is changed.
Co-Authored-By: HAL 9000
Cover response length and chunk decoding rules so incomplete or
ambiguous messages cannot pass unnoticed.
Co-Authored-By: HAL 9000
Cover persistence, closure, and pipelining rules so connection
reuse can be corrected against explicit expectations.
Refs: rust-bitcoin#659
Co-Authored-By: HAL 9000

@TheBlueMattTheBlueMatt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks!

}

#[test]
#[ignore = "TODO: reject bare CR in request protocol elements (RFC 9112 Section 2.2)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we actually intend to fix all these? I'm happy to see them fixed if we care, but its not clear to me that we do/should, at which point adding tests for them is just noise.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think we should. #661 is the start, but I intend to tackle these bit-by-bit in follow-ups.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW I don't think we should bother trying to be super strict on what the calling code passes. In this case specifically where the request is invalid, I think we should just accept it. The only exception would be if the request is bad in a way that will break our request code, ie if it might make two requests because it adds a \r\n\r\nGET... or something similar. I think that basically just means rejecting \r\ns and maybe rejecting standalone \r and \ns

@tnull
tnull requested a review from TheBlueMattJuly 20, 2026 07:51

@TheBlueMattTheBlueMatt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I skimmed about the first half of these. I think most of them its not worth enforcing - stuff where the server or client are maybe a bit confused but we can parse the resulting stream fine I really don't think we should add code to be strict on the RFC for.

}

#[test]
#[ignore = "TODO: reject bare CR in request protocol elements (RFC 9112 Section 2.2)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW I don't think we should bother trying to be super strict on what the calling code passes. In this case specifically where the request is invalid, I think we should just accept it. The only exception would be if the request is bad in a way that will break our request code, ie if it might make two requests because it adds a \r\n\r\nGET... or something similar. I think that basically just means rejecting \r\ns and maybe rejecting standalone \r and \ns

}

#[test]
#[ignore = "TODO: reject invalid request field names (RFC 9112 Sections 2.2 and 5)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should bother rejecting this.

}

#[test]
#[ignore = "TODO: reject conflicting Host fields (RFC 9112 Section 3.2)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should worry about stuff like this.


#[test]
#[ignore = "TODO: validate response status-line grammar (RFC 9112 Sections 2.3 and 4)"]
fn section_4_invalid_status_lines_are_rejected() {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should enforce this.

}

#[test]
#[ignore = "TODO: reject or ignore whitespace-prefixed fields (RFC 9112 Section 2.2)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see why we should enforce this.

#[test]
#[ignore = "TODO: reject repeated chunked transfer coding (RFC 9112 Section 6.1)"]
fn section_6_1_sender_rejects_repeated_chunked_coding() {
// RFC 9112 Section 6.1: a sender MUST NOT apply chunked transfer coding more than once.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see why we should reject this.

}

#[test]
#[ignore = "TODO: exclude chunked from TE requests (RFC 9112 Section 7.4)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's please not add parsing of random client headers just to enforce them.

}

#[test]
#[ignore = "TODO: add the TE connection option when sending TE (RFC 9112 Section 7.4)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

#[ignore = "TODO: treat successful CONNECT responses as tunnels (RFC 9112 Section 6.3)"]
fn section_6_3_successful_connect_ignores_framing_fields() {
// RFC 9112 Section 6.3: a client receiving a successful CONNECT response MUST ignore
// Content-Length and Transfer-Encoding because the connection becomes a tunnel.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we even going to support parsing this? Its not clear how to parse this if we're pipelining and if a proxy is this broken kinda who cares?

#[ignore = "TODO: reject Transfer-Encoding in HTTP/1.0 responses (RFC 9112 Section 6.1)"]
fn section_6_1_http_1_0_transfer_encoding_is_faulty() {
// RFC 9112 Section 6.1: a client receiving Transfer-Encoding in HTTP/1.0 MUST treat framing as
// faulty and close the connection.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is it worth our time to enforce this?

@tcharding

tcharding commented Jul 23, 2026

Copy link
Copy Markdown
Member

Please note development has migrated to https://git.rust-bitcoin.org/rust-bitcoin/corepc. Any further comments or pushes here on github may be ignored or lost. Closing since I know @tnull is ok with the migration.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@tnull@tcharding@TheBlueMatt
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

bitreq: Add RFC 9112 compliance test vectors - #660

Closed
tnull wants to merge 3 commits into
rust-bitcoin:masterfrom
tnull:2026-07-spec-compliance
Closed

bitreq: Add RFC 9112 compliance test vectors#660
tnull wants to merge 3 commits into
rust-bitcoin:masterfrom
tnull:2026-07-spec-compliance

Conversation

@tnull

Copy link
Copy Markdown
Collaborator

In #659 we recently discovered that we aren't fully compliant with RFC 9112 / HTTP 1.1.

As a first step of mitigation, we here add some test vectors that cover the central points. We opted to mark the (33!) failing checks as ignored, so we can revisit and fix them in following PRs (instead of cramming everything into one PR).

  • Response/cache poisoning: Extra unsolicited bytes can be accepted as the next response (§§6.3, 9.2).
  • Request smuggling/injection: Custom methods and headers allow CR/control-character injection; conflicting Host fields are transmitted (§§2.2–5).
  • Ambiguous message framing: Requests can contain both Content-Length and Transfer-Encoding; conflicting response lengths are accepted (§§6.1–6.3).
  • Incomplete responses accepted: Premature EOF, missing terminal zero chunks, and truncated header sections can be treated as complete (§8).
  • Invalid response syntax accepted: Malformed status lines, bare CR, whitespace-prefixed fields, and obsolete line folding are not handled as required (§§2–5).
  • Incorrect transfer-coding handling: Coding lists such as gzip, chunked, HTTP/1.0 Transfer-Encoding, and trailers are mishandled (§§6–7).
  • Broken connection semantics: HTTP/1.1 persistence incorrectly requires keep-alive; sent Connection: close can be ignored; tokenized options are not parsed correctly (§§9.3, 9.6).
  • CONNECT noncompliance: CONNECT uses the wrong request-target, omits the required proxy Host, and treats successful CONNECT responses as ordinary bodies (§§3.2, 6.3).

And more minor:

  • Consume 1xx informational responses until the final response.
  • Treat clean async EOF as successful for valid close-delimited responses.
  • Retry unanswered pipelined requests without immediately re-pipelining.

tnull added 3 commits July 11, 2026 15:21
Exercise the HTTP/1.1 wire grammar so request generation and
response parsing gaps are visible before behavior is changed.
Co-Authored-By: HAL 9000
Cover response length and chunk decoding rules so incomplete or
ambiguous messages cannot pass unnoticed.
Co-Authored-By: HAL 9000
Cover persistence, closure, and pipelining rules so connection
reuse can be corrected against explicit expectations.
Refs: rust-bitcoin#659
Co-Authored-By: HAL 9000

@TheBlueMattTheBlueMatt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks!

}

#[test]
#[ignore = "TODO: reject bare CR in request protocol elements (RFC 9112 Section 2.2)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we actually intend to fix all these? I'm happy to see them fixed if we care, but its not clear to me that we do/should, at which point adding tests for them is just noise.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think we should. #661 is the start, but I intend to tackle these bit-by-bit in follow-ups.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW I don't think we should bother trying to be super strict on what the calling code passes. In this case specifically where the request is invalid, I think we should just accept it. The only exception would be if the request is bad in a way that will break our request code, ie if it might make two requests because it adds a \r\n\r\nGET... or something similar. I think that basically just means rejecting \r\ns and maybe rejecting standalone \r and \ns

@tnull
tnull requested a review from TheBlueMattJuly 20, 2026 07:51

@TheBlueMattTheBlueMatt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I skimmed about the first half of these. I think most of them its not worth enforcing - stuff where the server or client are maybe a bit confused but we can parse the resulting stream fine I really don't think we should add code to be strict on the RFC for.

}

#[test]
#[ignore = "TODO: reject bare CR in request protocol elements (RFC 9112 Section 2.2)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW I don't think we should bother trying to be super strict on what the calling code passes. In this case specifically where the request is invalid, I think we should just accept it. The only exception would be if the request is bad in a way that will break our request code, ie if it might make two requests because it adds a \r\n\r\nGET... or something similar. I think that basically just means rejecting \r\ns and maybe rejecting standalone \r and \ns

}

#[test]
#[ignore = "TODO: reject invalid request field names (RFC 9112 Sections 2.2 and 5)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should bother rejecting this.

}

#[test]
#[ignore = "TODO: reject conflicting Host fields (RFC 9112 Section 3.2)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should worry about stuff like this.


#[test]
#[ignore = "TODO: validate response status-line grammar (RFC 9112 Sections 2.3 and 4)"]
fn section_4_invalid_status_lines_are_rejected() {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should enforce this.

}

#[test]
#[ignore = "TODO: reject or ignore whitespace-prefixed fields (RFC 9112 Section 2.2)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see why we should enforce this.

#[test]
#[ignore = "TODO: reject repeated chunked transfer coding (RFC 9112 Section 6.1)"]
fn section_6_1_sender_rejects_repeated_chunked_coding() {
// RFC 9112 Section 6.1: a sender MUST NOT apply chunked transfer coding more than once.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see why we should reject this.

}

#[test]
#[ignore = "TODO: exclude chunked from TE requests (RFC 9112 Section 7.4)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's please not add parsing of random client headers just to enforce them.

}

#[test]
#[ignore = "TODO: add the TE connection option when sending TE (RFC 9112 Section 7.4)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

#[ignore = "TODO: treat successful CONNECT responses as tunnels (RFC 9112 Section 6.3)"]
fn section_6_3_successful_connect_ignores_framing_fields() {
// RFC 9112 Section 6.3: a client receiving a successful CONNECT response MUST ignore
// Content-Length and Transfer-Encoding because the connection becomes a tunnel.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we even going to support parsing this? Its not clear how to parse this if we're pipelining and if a proxy is this broken kinda who cares?

#[ignore = "TODO: reject Transfer-Encoding in HTTP/1.0 responses (RFC 9112 Section 6.1)"]
fn section_6_1_http_1_0_transfer_encoding_is_faulty() {
// RFC 9112 Section 6.1: a client receiving Transfer-Encoding in HTTP/1.0 MUST treat framing as
// faulty and close the connection.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is it worth our time to enforce this?

@tcharding

tcharding commented Jul 23, 2026

Copy link
Copy Markdown
Member

Please note development has migrated to https://git.rust-bitcoin.org/rust-bitcoin/corepc. Any further comments or pushes here on github may be ignored or lost. Closing since I know @tnull is ok with the migration.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@tnull@tcharding@TheBlueMatt
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

bitreq: Add RFC 9112 compliance test vectors - #660

Closed
tnull wants to merge 3 commits into
rust-bitcoin:masterfrom
tnull:2026-07-spec-compliance
Closed

bitreq: Add RFC 9112 compliance test vectors#660
tnull wants to merge 3 commits into
rust-bitcoin:masterfrom
tnull:2026-07-spec-compliance

Conversation

@tnull

Copy link
Copy Markdown
Collaborator

In #659 we recently discovered that we aren't fully compliant with RFC 9112 / HTTP 1.1.

As a first step of mitigation, we here add some test vectors that cover the central points. We opted to mark the (33!) failing checks as ignored, so we can revisit and fix them in following PRs (instead of cramming everything into one PR).

  • Response/cache poisoning: Extra unsolicited bytes can be accepted as the next response (§§6.3, 9.2).
  • Request smuggling/injection: Custom methods and headers allow CR/control-character injection; conflicting Host fields are transmitted (§§2.2–5).
  • Ambiguous message framing: Requests can contain both Content-Length and Transfer-Encoding; conflicting response lengths are accepted (§§6.1–6.3).
  • Incomplete responses accepted: Premature EOF, missing terminal zero chunks, and truncated header sections can be treated as complete (§8).
  • Invalid response syntax accepted: Malformed status lines, bare CR, whitespace-prefixed fields, and obsolete line folding are not handled as required (§§2–5).
  • Incorrect transfer-coding handling: Coding lists such as gzip, chunked, HTTP/1.0 Transfer-Encoding, and trailers are mishandled (§§6–7).
  • Broken connection semantics: HTTP/1.1 persistence incorrectly requires keep-alive; sent Connection: close can be ignored; tokenized options are not parsed correctly (§§9.3, 9.6).
  • CONNECT noncompliance: CONNECT uses the wrong request-target, omits the required proxy Host, and treats successful CONNECT responses as ordinary bodies (§§3.2, 6.3).

And more minor:

  • Consume 1xx informational responses until the final response.
  • Treat clean async EOF as successful for valid close-delimited responses.
  • Retry unanswered pipelined requests without immediately re-pipelining.

tnull added 3 commits July 11, 2026 15:21
Exercise the HTTP/1.1 wire grammar so request generation and
response parsing gaps are visible before behavior is changed.
Co-Authored-By: HAL 9000
Cover response length and chunk decoding rules so incomplete or
ambiguous messages cannot pass unnoticed.
Co-Authored-By: HAL 9000
Cover persistence, closure, and pipelining rules so connection
reuse can be corrected against explicit expectations.
Refs: rust-bitcoin#659
Co-Authored-By: HAL 9000

@TheBlueMattTheBlueMatt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks!

}

#[test]
#[ignore = "TODO: reject bare CR in request protocol elements (RFC 9112 Section 2.2)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we actually intend to fix all these? I'm happy to see them fixed if we care, but its not clear to me that we do/should, at which point adding tests for them is just noise.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think we should. #661 is the start, but I intend to tackle these bit-by-bit in follow-ups.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW I don't think we should bother trying to be super strict on what the calling code passes. In this case specifically where the request is invalid, I think we should just accept it. The only exception would be if the request is bad in a way that will break our request code, ie if it might make two requests because it adds a \r\n\r\nGET... or something similar. I think that basically just means rejecting \r\ns and maybe rejecting standalone \r and \ns

@tnull
tnull requested a review from TheBlueMattJuly 20, 2026 07:51

@TheBlueMattTheBlueMatt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I skimmed about the first half of these. I think most of them its not worth enforcing - stuff where the server or client are maybe a bit confused but we can parse the resulting stream fine I really don't think we should add code to be strict on the RFC for.

}

#[test]
#[ignore = "TODO: reject bare CR in request protocol elements (RFC 9112 Section 2.2)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW I don't think we should bother trying to be super strict on what the calling code passes. In this case specifically where the request is invalid, I think we should just accept it. The only exception would be if the request is bad in a way that will break our request code, ie if it might make two requests because it adds a \r\n\r\nGET... or something similar. I think that basically just means rejecting \r\ns and maybe rejecting standalone \r and \ns

}

#[test]
#[ignore = "TODO: reject invalid request field names (RFC 9112 Sections 2.2 and 5)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should bother rejecting this.

}

#[test]
#[ignore = "TODO: reject conflicting Host fields (RFC 9112 Section 3.2)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should worry about stuff like this.


#[test]
#[ignore = "TODO: validate response status-line grammar (RFC 9112 Sections 2.3 and 4)"]
fn section_4_invalid_status_lines_are_rejected() {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should enforce this.

}

#[test]
#[ignore = "TODO: reject or ignore whitespace-prefixed fields (RFC 9112 Section 2.2)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see why we should enforce this.

#[test]
#[ignore = "TODO: reject repeated chunked transfer coding (RFC 9112 Section 6.1)"]
fn section_6_1_sender_rejects_repeated_chunked_coding() {
// RFC 9112 Section 6.1: a sender MUST NOT apply chunked transfer coding more than once.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see why we should reject this.

}

#[test]
#[ignore = "TODO: exclude chunked from TE requests (RFC 9112 Section 7.4)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's please not add parsing of random client headers just to enforce them.

}

#[test]
#[ignore = "TODO: add the TE connection option when sending TE (RFC 9112 Section 7.4)"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

#[ignore = "TODO: treat successful CONNECT responses as tunnels (RFC 9112 Section 6.3)"]
fn section_6_3_successful_connect_ignores_framing_fields() {
// RFC 9112 Section 6.3: a client receiving a successful CONNECT response MUST ignore
// Content-Length and Transfer-Encoding because the connection becomes a tunnel.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we even going to support parsing this? Its not clear how to parse this if we're pipelining and if a proxy is this broken kinda who cares?

#[ignore = "TODO: reject Transfer-Encoding in HTTP/1.0 responses (RFC 9112 Section 6.1)"]
fn section_6_1_http_1_0_transfer_encoding_is_faulty() {
// RFC 9112 Section 6.1: a client receiving Transfer-Encoding in HTTP/1.0 MUST treat framing as
// faulty and close the connection.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is it worth our time to enforce this?

@tcharding

tcharding commented Jul 23, 2026

Copy link
Copy Markdown
Member

Please note development has migrated to https://git.rust-bitcoin.org/rust-bitcoin/corepc. Any further comments or pushes here on github may be ignored or lost. Closing since I know @tnull is ok with the migration.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@tnull@tcharding@TheBlueMatt