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

debugger: fix debugger failure when passing commands with non-latin symbols #11841

Closed
wants to merge 3 commits into from
Closed

debugger: fix debugger failure when passing commands with non-latin symbols #11841

wants to merge 3 commits into from

Conversation

Let0s
Copy link

@Let0s Let0s commented Mar 14, 2017

Debug agent incorrectly used Content-Length and cut Content-Length symbols instead of Content-Length bytes from debugger protocol messages. This causes incorrect command body extraction and parsing that leads to debugger disconnection.

I use to fix the issue code similar to https://github.com/nodejs/node/blob/master/lib/_debugger.js#L136
This fixes debugger problem mistakenly reported here microsoft/vscode#17389

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • tests and/or benchmarks are included
  • documentation is changed or added
  • commit message follows commit guidelines
Affected core subsystem(s)

debugger

@bnoordhuis
Copy link
Member

I don't think this PR by itself is sufficient. I had a look at Client.prototype._transform and it does this.buffer += data but data is a Buffer object as far as I can tell.

That's going to mangle UTF-8 character sequences when the sequence is split across buffer boundaries. I didn't test it but I suspect the Client constructor should have a Transform.call({ decodeStrings: true }) in it.

@quanterion
Copy link

quanterion commented Mar 15, 2017

In debugger typeof this.data is string. Even more in Client.prototype._transform there are this.buffer.match() this.buffer.startsWith() function calls that suggests that this.buffer should be a string.

Even more, concatenation of Buffer objects like this this.buffer += data is not possible (it will result in string)

@bnoordhuis
Copy link
Member

@quanterion data is coerced to a string by this.buffer += data but that does the wrong thing when data ends in a partial UTF-8 character sequence. Here's an example:

> var x = Buffer.from('λ')
undefined
> x
<Buffer ce bb>
> '' + x
'λ'
> x.slice(0,1) + x.slice(1)
'��'

@Let0s
Copy link
Author

Let0s commented Mar 16, 2017

@bnoordhuis does new commit resolve all possible cases with incorrect data transformation?

Copy link
Member

@bnoordhuis bnoordhuis left a comment

Choose a reason for hiding this comment

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

Mostly LGTM. Would it be possible to add a regression test?

The tests in test/debugger aren't well-maintained but we have tests in test/sequential and test/parallel that you can use as examples (e.g., test/fixtures/debugger-repeat-last.js.)

break;

this.push(new Command(this.headers, this.buffer.slice(0, len)));
this.push(new Command(this.headers, this.buffer.slice(0, len).toString('utf8')));
Copy link
Member

Choose a reason for hiding this comment

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

Long line. Can you run make test, it also lints source files.

@@ -97,7 +97,7 @@ function Client(agent, socket) {
// Parse incoming data
this.state = 'headers';
this.headers = {};
this.buffer = '';
this.buffer = new Buffer(0);
Copy link
Member

Choose a reason for hiding this comment

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

Can you use Buffer.alloc(0) here?

@Let0s
Copy link
Author

Let0s commented Mar 16, 2017

@bnoordhuis where should test file be located? In debugger folder or another?

@bnoordhuis
Copy link
Member

@Let0s test/parallel, unless it cannot run in parallel with other tests. In that case it should go into test/sequential.

if (!match)
return this.destroy('Expected header, but failed to parse it');

this.headers[match[1].toLowerCase()] = match[2];

this.buffer = this.buffer.slice(match[0].length);
this.buffer = this.buffer.slice(Buffer.byteLength(match[0], 'utf8'));
Copy link
Member

Choose a reason for hiding this comment

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

There will likely be a bit of a performance hit on this given the multiple utf8 conversions involved on chunks of the buffer (the toString above, the byteLength call here). We should benchmark this change to see how much of a hit this causes.

Copy link
Member

Choose a reason for hiding this comment

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

this.buffer could be turned into a string_decoder.StringDecoder. It's more structured than manual buffer->string manipulation and should be more efficient too.

@bnoordhuis
Copy link
Member

@Let0s The old debugger has been removed in the master branch. If you still want to pursue this, can you file a pull request against the v6.x-staging branch? We can discuss back-porting to v4.x once it lands in v6.x.

I'll take the liberty of closing this one.

@bnoordhuis bnoordhuis closed this May 15, 2017
@Let0s
Copy link
Author

Let0s commented May 17, 2017

@bnoordhuis I don't think I can make tests for this PR (I don't have so experience in node and in "writing pure code"), so I'll leave it and I will hope that someone will continue it.

@refack
Copy link
Contributor

refack commented May 17, 2017

@Let0s is it still a real problem for you?
If solving this helps you, I can pick it up from here.

@Let0s
Copy link
Author

Let0s commented May 18, 2017

@refack No, it's not a problem for me. I encountered with this in forked project, and I decided to inform base repo about this. Maybe it don't need to be solved if noone else met this problem.

@refack refack self-assigned this May 18, 2017
@refack
Copy link
Contributor

refack commented May 18, 2017

@refack No, it's not a problem for me. I encountered with this in forked project, and I decided to inform base repo about this. Maybe it don't need to be solved if noone else met this problem.

@Let0s thank you for the answer. I've added this to my TODO list, but at a low priority...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants