tls_wrap: reach error reporting for UV_EPROTO
Do not swallow error details when reporting UV_EPROTO asynchronously, and when creating artificial errors. Fix: #3692 PR-URL: https://github.com/nodejs/node/pull/4885 Reviewed-By: Shigeki Ohtsu <ohtsu@iij.ad.jp> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
This commit is contained in:
parent
b4313cf9a2
commit
ff4006c7b0
@ -760,7 +760,7 @@ function afterWrite(status, handle, req, err) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
var ex = exceptionWithHostPort(status, 'write', req.address, req.port);
|
var ex = errnoException(status, 'write', req.error);
|
||||||
debug('write failure', ex);
|
debug('write failure', ex);
|
||||||
self._destroy(ex, req.cb);
|
self._destroy(ex, req.cb);
|
||||||
return;
|
return;
|
||||||
|
@ -22,8 +22,15 @@ class StreamReq {
|
|||||||
explicit StreamReq(DoneCb cb) : cb_(cb) {
|
explicit StreamReq(DoneCb cb) : cb_(cb) {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Done(int status) {
|
inline void Done(int status, const char* error_str = nullptr) {
|
||||||
cb_(static_cast<Req*>(this), status);
|
Req* req = static_cast<Req*>(this);
|
||||||
|
Environment* env = req->env();
|
||||||
|
if (error_str != nullptr) {
|
||||||
|
req->object()->Set(env->error_string(),
|
||||||
|
OneByteString(env->isolate(), error_str));
|
||||||
|
}
|
||||||
|
|
||||||
|
cb_(req, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -92,7 +92,7 @@ void TLSWrap::MakePending() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool TLSWrap::InvokeQueued(int status) {
|
bool TLSWrap::InvokeQueued(int status, const char* error_str) {
|
||||||
if (pending_write_items_.IsEmpty())
|
if (pending_write_items_.IsEmpty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -100,7 +100,7 @@ bool TLSWrap::InvokeQueued(int status) {
|
|||||||
WriteItemList queue;
|
WriteItemList queue;
|
||||||
pending_write_items_.MoveBack(&queue);
|
pending_write_items_.MoveBack(&queue);
|
||||||
while (WriteItem* wi = queue.PopFront()) {
|
while (WriteItem* wi = queue.PopFront()) {
|
||||||
wi->w_->Done(status);
|
wi->w_->Done(status, error_str);
|
||||||
delete wi;
|
delete wi;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -484,11 +484,12 @@ bool TLSWrap::ClearIn() {
|
|||||||
|
|
||||||
// Error or partial write
|
// Error or partial write
|
||||||
int err;
|
int err;
|
||||||
Local<Value> arg = GetSSLError(written, &err, &error_);
|
const char* error_str = nullptr;
|
||||||
|
Local<Value> arg = GetSSLError(written, &err, &error_str);
|
||||||
if (!arg.IsEmpty()) {
|
if (!arg.IsEmpty()) {
|
||||||
MakePending();
|
MakePending();
|
||||||
if (!InvokeQueued(UV_EPROTO))
|
InvokeQueued(UV_EPROTO, error_str);
|
||||||
ClearError();
|
delete[] error_str;
|
||||||
clear_in_->Reset();
|
clear_in_->Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -589,8 +590,15 @@ int TLSWrap::DoWrite(WriteWrap* w,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ssl_ == nullptr)
|
if (ssl_ == nullptr) {
|
||||||
|
ClearError();
|
||||||
|
|
||||||
|
static char msg[] = "Write after DestroySSL";
|
||||||
|
char* tmp = new char[sizeof(msg)];
|
||||||
|
memcpy(tmp, msg, sizeof(msg));
|
||||||
|
error_ = tmp;
|
||||||
return UV_EPROTO;
|
return UV_EPROTO;
|
||||||
|
}
|
||||||
|
|
||||||
crypto::MarkPopErrorOnReturn mark_pop_error_on_return;
|
crypto::MarkPopErrorOnReturn mark_pop_error_on_return;
|
||||||
|
|
||||||
@ -775,7 +783,7 @@ void TLSWrap::DestroySSL(const FunctionCallbackInfo<Value>& args) {
|
|||||||
wrap->MakePending();
|
wrap->MakePending();
|
||||||
|
|
||||||
// And destroy
|
// And destroy
|
||||||
wrap->InvokeQueued(UV_ECANCELED);
|
wrap->InvokeQueued(UV_ECANCELED, "Canceled because of SSL destruction");
|
||||||
|
|
||||||
// Destroy the SSL structure and friends
|
// Destroy the SSL structure and friends
|
||||||
wrap->SSLWrap<TLSWrap>::DestroySSL();
|
wrap->SSLWrap<TLSWrap>::DestroySSL();
|
||||||
|
@ -89,7 +89,7 @@ class TLSWrap : public AsyncWrap,
|
|||||||
bool ClearIn();
|
bool ClearIn();
|
||||||
void ClearOut();
|
void ClearOut();
|
||||||
void MakePending();
|
void MakePending();
|
||||||
bool InvokeQueued(int status);
|
bool InvokeQueued(int status, const char* error_str = nullptr);
|
||||||
|
|
||||||
inline void Cycle() {
|
inline void Cycle() {
|
||||||
// Prevent recursion
|
// Prevent recursion
|
||||||
|
29
test/parallel/test-tls-junk-server.js
Normal file
29
test/parallel/test-tls-junk-server.js
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
'use strict';
|
||||||
|
const common = require('../common');
|
||||||
|
|
||||||
|
if (!common.hasCrypto) {
|
||||||
|
console.log('1..0 # Skipped: missing crypto');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const assert = require('assert');
|
||||||
|
const https = require('https');
|
||||||
|
const net = require('net');
|
||||||
|
|
||||||
|
const server = net.createServer(function(s) {
|
||||||
|
s.once('data', function() {
|
||||||
|
s.end('I was waiting for you, hello!', function() {
|
||||||
|
s.destroy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
server.listen(common.PORT, function() {
|
||||||
|
const req = https.request({ port: common.PORT });
|
||||||
|
req.end();
|
||||||
|
|
||||||
|
req.once('error', common.mustCall(function(err) {
|
||||||
|
assert(/unknown protocol/.test(err.message));
|
||||||
|
server.close();
|
||||||
|
}));
|
||||||
|
});
|
Loading…
x
Reference in New Issue
Block a user