Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error if message is bigger than Content-Length #39133

Open
wants to merge 12 commits into
base: main
Choose a base branch
from

Conversation

betochf
Copy link

@betochf betochf commented Jun 24, 2021

Pr for issue #39041

The test for the changes is very simple, it just contains a 200 request with a header specifying the "Content-Lenght", in this case with a size of 2 bytes, with a response of 4 so the error could be triggered.

tests:

  • If we change the value of the Content-Lenght for the actual one or a bigger one, we have no error.
  • Finally, we do a request with no headers just to prove that the code still running, even with the new #changes.

@github-actions github-actions bot added errors Issues and PRs related to JavaScript errors originated in Node.js core. http Issues or PRs related to the http subsystem. needs-ci PRs that need a full CI run. labels Jun 24, 2021
@@ -66,7 +66,8 @@ const {
ERR_STREAM_ALREADY_FINISHED,
ERR_STREAM_WRITE_AFTER_END,
ERR_STREAM_NULL_VALUES,
ERR_STREAM_DESTROYED
ERR_STREAM_DESTROYED,
ERR_CONTENT_LENGTH_HEADER
Copy link
Member

@ronag ronag Jun 24, 2021

Choose a reason for hiding this comment

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

Suggested change
ERR_CONTENT_LENGTH_HEADER
ERR_CONTENT_LENGTH_MISMATCH,

Copy link
Contributor

Choose a reason for hiding this comment

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

nit: Could this list also be sorted in alphabetical order?

Copy link
Author

Choose a reason for hiding this comment

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

Ok, thanks for the feedback, would make the changes

Copy link
Member

@ronag ronag left a comment

Choose a reason for hiding this comment

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

Would also be nice if you check content length in .end() to make sure not to few bytes have been written as well.

lib/_http_outgoing.js Outdated Show resolved Hide resolved
lib/_http_outgoing.js Outdated Show resolved Hide resolved
@VoltrexKeyva
Copy link
Member

Unrelated documentation changes in doc/api/errors.md. (Line 9 to Line 805 | Line 821 to Line 3241)

@betochf
Copy link
Author

betochf commented Jun 24, 2021

Hey @ronag for .end(), how many bytes would be a good amount so the error is not triggered?
I was thinking that it should be at least half of the size of the Content-Length

@ronag
Copy link
Member

ronag commented Jun 25, 2021

Hey @ronag for .end(), how many bytes would be a good amount so the error is not triggered?
I was thinking that it should be at least half of the size of the Content-Length

If it doesn’t match content length then error

@@ -514,6 +517,9 @@ function processHeader(self, state, key, value, validate) {
function storeHeader(self, state, key, value, validate) {
if (validate)
validateHeaderValue(key, value);
if (key === 'Content-Length') {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
if (key === 'Content-Length') {
if (key.toLowerCase() === 'content-length') {

Copy link

@mpodolsk mpodolsk Jan 3, 2022

Choose a reason for hiding this comment

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

https://nodejs.org/es/docs/guides/anatomy-of-an-http-transaction/

It's important to note here that all headers are represented in lower-case only, regardless of how the client actually sent them. This simplifies the task of parsing headers for whatever purpose.

@@ -575,6 +581,10 @@ OutgoingMessage.prototype.setHeader = function setHeader(name, value) {
validateHeaderName(name);
validateHeaderValue(name, value);

if (name === 'content-length') {
this._contentLength = NumberParseInt(value);
}
Copy link
Member

Choose a reason for hiding this comment

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

Why? Isn’t store header enough?

Copy link
Author

Choose a reason for hiding this comment

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

Oh sorry, shouldn't be there, my mistake

Copy link
Author

Choose a reason for hiding this comment

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

I checked the code again and store header is not enough, the Content-length is not set when setHeader is used... I think it happens because it never goes throw processHeader

Copy link
Member

Choose a reason for hiding this comment

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

Putting inside the validation function is wrong though.

Copy link
Author

Choose a reason for hiding this comment

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

It seemed right sorry, I'll create a new function for the validating the content length

lib/_http_outgoing.js Outdated Show resolved Hide resolved
lib/_http_outgoing.js Outdated Show resolved Hide resolved
lib/_http_outgoing.js Outdated Show resolved Hide resolved
lib/_http_outgoing.js Outdated Show resolved Hide resolved
lib/_http_outgoing.js Outdated Show resolved Hide resolved
Copy link
Member

@ronag ronag left a comment

Choose a reason for hiding this comment

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

A lot of unrelated doc changes...

lib/_http_outgoing.js Outdated Show resolved Hide resolved
@RaisinTen
Copy link
Contributor

@betochf Could you please rebase and resolve the merge conflicts?

@betochf
Copy link
Author

betochf commented Jul 5, 2021

@RaisinTen done, it was an error in the Doc

let headers = this[kOutHeaders];
if (headers === null)
this[kOutHeaders] = headers = ObjectCreate(null);

Copy link
Member

Choose a reason for hiding this comment

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

Unrelated change

Copy link

Choose a reason for hiding this comment

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

+1. By the way, are changes in doc/api/errors.md also required? It seems like most of them are unrelated to an issue as well.

@@ -756,6 +772,12 @@ function write_(msg, chunk, encoding, callback, fromEnd) {
return false;
}

if (msg._contentLength) {
if (msg[kBytesWritten] > msg._contentLength) {
Copy link
Member

Choose a reason for hiding this comment

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

You can combine these two if statements

if (msg[kBytesWritten] > msg._contentLength) {
throw new ERR_CONTENT_LENGTH_MISMATCH(msg._contentLength, msg[kBytesWritten]);
}
}
Copy link
Member

Choose a reason for hiding this comment

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

Why is this check needed if you already have it below?

Copy link
Member

@ronag ronag left a comment

Choose a reason for hiding this comment

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

Needs more tests.

@betochf
Copy link
Author

betochf commented Jul 9, 2021

@ronag I did the changes... which other tests should I try?

@Ayase-252
Copy link
Member

I think 3 tests should be added at least:

  • when actual length is mismatched (more or less) with Content-Length, it should throw;
  • when Content-Length is negative, it should throw;

@@ -81,7 +84,7 @@ const HIGH_WATER_MARK = getDefaultHighWaterMark();
const { CRLF } = common;

const kCorked = Symbol('corked');

const kBytesWritten = Symbol ('bytes');
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
const kBytesWritten = Symbol ('bytes');
const kBytesWritten = Symbol('bytes');

@@ -849,6 +871,11 @@ OutgoingMessage.prototype.end = function end(chunk, encoding, callback) {
this.socket.cork();
}

const byteCount = (this[kBytesWritten] + chunk.length);
if (this._contentLength && (byteCount) !== this._contentLength) {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
if (this._contentLength && (byteCount) !== this._contentLength) {
if (this._contentLength !== undefined && (byteCount) !== this._contentLength) {

@@ -1191,6 +1199,10 @@ E('ERR_INVALID_CHAR',
}
return msg;
}, TypeError);
E('ERR_INVALID_CONTENT_LENGTH', function(size) {
Copy link
Member

Choose a reason for hiding this comment

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

ERR_INVALID_ARG_VALUE could be used instead.

@@ -849,6 +871,11 @@ OutgoingMessage.prototype.end = function end(chunk, encoding, callback) {
this.socket.cork();
}

const byteCount = (this[kBytesWritten] + chunk.length);
Copy link
Member

Choose a reason for hiding this comment

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

This may not be entirely accurate in every case due to content encoding. For instance, if I pass in w.end('afef', 'hex'), I'm only writing 2 bytes. The calculation here needs to take into consideration the encoding and the actual byte length.

Comment on lines +866 to +869
let msg;
if (byteCount < contentLength) {
msg = 'less';
} else msg = 'more';
Copy link

Choose a reason for hiding this comment

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

Suggested change
let msg;
if (byteCount < contentLength) {
msg = 'less';
} else msg = 'more';
const msg = byteCount < contentLength ? 'less' : 'more';

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
errors Issues and PRs related to JavaScript errors originated in Node.js core. http Issues or PRs related to the http subsystem. needs-ci PRs that need a full CI run.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants