From 0ec3770767dd24254d137ac45fe34897ec0443b8 Mon Sep 17 00:00:00 2001 From: Fedor Indutny Date: Thu, 23 Jan 2014 15:35:50 +0400 Subject: [PATCH 1/5] doc: readline document TTY utils fix #6933 --- doc/api/readline.markdown | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/doc/api/readline.markdown b/doc/api/readline.markdown index bcfbe4f590..1fa08a1905 100644 --- a/doc/api/readline.markdown +++ b/doc/api/readline.markdown @@ -281,3 +281,23 @@ line interface: process.exit(0); }); +## readline.cursorTo(stream, x, y) + +Move cursor to the specified position in a given TTY stream. + +## readline.moveCursor(stream, dx, dy) + +Move cursor relative to it's current position in a given TTY stream. + +## readline.clearLine(stream, dir) + +Clears current line of given TTY stream in a specified direction. +`dir` should have one of following values: + +* `-1` - to the left from cursor +* `1` - to the right from cursor +* `0` - the entire line + +## readline.clearScreenDown(stream) + +Clears the screen from the current position of the cursor down. From 896e19330ad06ace8973c5d7b75d2de538228062 Mon Sep 17 00:00:00 2001 From: Fedor Indutny Date: Thu, 23 Jan 2014 14:27:36 +0400 Subject: [PATCH 2/5] deps: backport b5135bbc from c-ares repo Original commit message: ares_parse_txt_reply: return a ares_txt_reply node for each sub-string Previously, the function would wrongly return all substrings merged into one. fix #6931 --- deps/cares/src/ares_parse_txt_reply.c | 78 +++++++++++++-------------- 1 file changed, 37 insertions(+), 41 deletions(-) diff --git a/deps/cares/src/ares_parse_txt_reply.c b/deps/cares/src/ares_parse_txt_reply.c index 51653328eb..e1ebbbea90 100644 --- a/deps/cares/src/ares_parse_txt_reply.c +++ b/deps/cares/src/ares_parse_txt_reply.c @@ -54,7 +54,7 @@ int ares_parse_txt_reply (const unsigned char *abuf, int alen, struct ares_txt_reply **txt_out) { - size_t substr_len, str_len; + size_t substr_len; unsigned int qdcount, ancount, i; const unsigned char *aptr; const unsigned char *strptr; @@ -116,23 +116,6 @@ ares_parse_txt_reply (const unsigned char *abuf, int alen, /* Check if we are really looking at a TXT record */ if (rr_class == C_IN && rr_type == T_TXT) { - /* Allocate storage for this TXT answer appending it to the list */ - txt_curr = ares_malloc_data(ARES_DATATYPE_TXT_REPLY); - if (!txt_curr) - { - status = ARES_ENOMEM; - break; - } - if (txt_last) - { - txt_last->next = txt_curr; - } - else - { - txt_head = txt_curr; - } - txt_last = txt_curr; - /* * There may be multiple substrings in a single TXT record. Each * substring may be up to 255 characters in length, with a @@ -141,36 +124,49 @@ ares_parse_txt_reply (const unsigned char *abuf, int alen, * substrings contained therein. */ - /* Compute total length to allow a single memory allocation */ strptr = aptr; while (strptr < (aptr + rr_len)) { substr_len = (unsigned char)*strptr; - txt_curr->length += substr_len; - strptr += substr_len + 1; - } + if (strptr + substr_len + 1 > aptr + rr_len) + { + status = ARES_EBADRESP; + break; + } + + ++strptr; + + /* Allocate storage for this TXT answer appending it to the list */ + txt_curr = ares_malloc_data(ARES_DATATYPE_TXT_REPLY); + if (!txt_curr) + { + status = ARES_ENOMEM; + break; + } + if (txt_last) + { + txt_last->next = txt_curr; + } + else + { + txt_head = txt_curr; + } + txt_last = txt_curr; + + txt_curr->length = substr_len; + txt_curr->txt = malloc (substr_len + 1/* Including null byte */); + if (txt_curr->txt == NULL) + { + status = ARES_ENOMEM; + break; + } + memcpy ((char *) txt_curr->txt, strptr, substr_len); + + /* Make sure we NULL-terminate */ + txt_curr->txt[substr_len] = 0; - /* Including null byte */ - txt_curr->txt = malloc (txt_curr->length + 1); - if (txt_curr->txt == NULL) - { - status = ARES_ENOMEM; - break; - } - - /* Step through the list of substrings, concatenating them */ - str_len = 0; - strptr = aptr; - while (strptr < (aptr + rr_len)) - { - substr_len = (unsigned char)*strptr; - strptr++; - memcpy ((char *) txt_curr->txt + str_len, strptr, substr_len); - str_len += substr_len; strptr += substr_len; } - /* Make sure we NULL-terminate */ - *((char *) txt_curr->txt + txt_curr->length) = '\0'; } /* Don't lose memory in the next iteration */ From 00efcb4cd7609dcefad8acba915d850480436457 Mon Sep 17 00:00:00 2001 From: Fedor Indutny Date: Thu, 23 Jan 2014 01:15:04 +0400 Subject: [PATCH 3/5] net: reset `endEmitted` on reconnect fix #6908 --- lib/net.js | 1 + test/simple/test-net-reconnect.js | 3 +++ 2 files changed, 4 insertions(+) diff --git a/lib/net.js b/lib/net.js index 5489b21910..e624adfcc3 100644 --- a/lib/net.js +++ b/lib/net.js @@ -781,6 +781,7 @@ Socket.prototype.connect = function(options, cb) { if (this.destroyed) { this._readableState.reading = false; this._readableState.ended = false; + this._readableState.endEmitted = false; this._writableState.ended = false; this._writableState.ending = false; this._writableState.finished = false; diff --git a/test/simple/test-net-reconnect.js b/test/simple/test-net-reconnect.js index f4b19977ee..ffc2a73c63 100644 --- a/test/simple/test-net-reconnect.js +++ b/test/simple/test-net-reconnect.js @@ -27,6 +27,7 @@ var net = require('net'); var N = 50; var c = 0; var client_recv_count = 0; +var client_end_count = 0; var disconnect_count = 0; var server = net.createServer(function(socket) { @@ -67,6 +68,7 @@ server.listen(common.PORT, function() { client.on('end', function() { console.error('CLIENT end'); + client_end_count++; }); client.on('close', function(had_error) { @@ -82,5 +84,6 @@ server.listen(common.PORT, function() { process.on('exit', function() { assert.equal(N + 1, disconnect_count); assert.equal(N + 1, client_recv_count); + assert.equal(N + 1, client_end_count); }); From b4c4e0bbaa19616f41857e20c2dc2824c780baf4 Mon Sep 17 00:00:00 2001 From: Fedor Indutny Date: Sun, 26 Jan 2014 20:09:14 +0400 Subject: [PATCH 4/5] crypto: throw on SignFinal failure fix #6963 --- src/node_crypto.cc | 13 +++++++++++-- test/simple/test-crypto.js | 13 +++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/node_crypto.cc b/src/node_crypto.cc index 87025dd6b7..d9eda59b8d 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -3005,9 +3005,15 @@ class Sign : public ObjectWrap { if(!BIO_write(bp, key_pem, key_pemLen)) return 0; pkey = PEM_read_bio_PrivateKey( bp, NULL, NULL, NULL ); - if (pkey == NULL) return 0; + if (pkey == NULL) { + ERR_print_errors_fp(stderr); + return 0; + } - EVP_SignFinal(&mdctx, *md_value, md_len, pkey); + if (!EVP_SignFinal(&mdctx, *md_value, md_len, pkey)) { + ERR_print_errors_fp(stderr); + return 0; + } EVP_MD_CTX_cleanup(&mdctx); initialised_ = false; EVP_PKEY_free(pkey); @@ -3107,8 +3113,11 @@ class Sign : public ObjectWrap { int r = sign->SignFinal(&md_value, &md_len, buf, len); if (r == 0) { + delete [] buf; + delete [] md_value; md_value = NULL; md_len = r; + return ThrowException(Exception::Error(String::New("SignFinal error"))); } delete [] buf; diff --git a/test/simple/test-crypto.js b/test/simple/test-crypto.js index abb767f762..96a269f4d0 100644 --- a/test/simple/test-crypto.js +++ b/test/simple/test-crypto.js @@ -937,3 +937,16 @@ assert.throws(function() { assert.throws(function() { crypto.createVerify('RSA-SHA1').update('0', 'hex'); }, /Bad input string/); + +assert.throws(function() { + var private = [ + '-----BEGIN RSA PRIVATE KEY-----', + 'MIGrAgEAAiEA+3z+1QNF2/unumadiwEr+C5vfhezsb3hp4jAnCNRpPcCAwEAAQIgQNriSQK4', + 'EFwczDhMZp2dvbcz7OUUyt36z3S4usFPHSECEQD/41K7SujrstBfoCPzwC1xAhEA+5kt4BJy', + 'eKN7LggbF3Dk5wIQN6SL+fQ5H/+7NgARsVBp0QIRANxYRukavs4QvuyNhMx+vrkCEQCbf6j/', + 'Ig6/HueCK/0Jkmp+', + '-----END RSA PRIVATE KEY-----', + '' + ].join('\n'); + crypto.createSign('RSA-SHA256').update('test').sign(private); +}, /SignFinal/); From d2de8ba34dc57d78a0bd0fedc4bd05e5c4457bac Mon Sep 17 00:00:00 2001 From: Jun Ma Date: Sun, 26 Jan 2014 01:50:17 +0800 Subject: [PATCH 5/5] net: make Socket destroy() re-entrance safe So that we are free to call socket.destroy() in error event handler. fix #6769 --- lib/net.js | 5 ++++- test/simple/test-net-stream.js | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/lib/net.js b/lib/net.js index e624adfcc3..31de90cb02 100644 --- a/lib/net.js +++ b/lib/net.js @@ -469,8 +469,11 @@ Socket.prototype._destroy = function(exception, cb) { this._handle = null; } - fireErrorCallbacks(); + // we set destroyed to true before firing error callbacks in order + // to make it re-entrance safe in case Socket.prototype.destroy() + // is called within callbacks this.destroyed = true; + fireErrorCallbacks(); if (this.server) { COUNTER_NET_SERVER_CONNECTION_CLOSE(this); diff --git a/test/simple/test-net-stream.js b/test/simple/test-net-stream.js index 429995ab93..9f2db51be8 100644 --- a/test/simple/test-net-stream.js +++ b/test/simple/test-net-stream.js @@ -37,3 +37,36 @@ s.destroy(); assert.equal(9, s.server.connections); s.destroy(); assert.equal(9, s.server.connections); + +var SIZE = 2E6; +var N = 10; +var buf = new Buffer(SIZE); +buf.fill(0x61); // 'a' + +var server = net.createServer(function(socket) { + socket.setNoDelay(); + + socket.on('error', function(err) { + socket.destroy(); + }).on('close', function() { + server.close(); + }) + + for (var i = 0; i < N; ++i) { + socket.write(buf, function() { }); + } + socket.end(); + +}).listen(common.PORT, function() { + var conn = net.connect(common.PORT); + conn.on('data', function(buf) { + conn.pause(); + setTimeout(function() { + conn.destroy(); + }, 20); + }); + }); + +process.on('exit', function() { + assert.equal(server.connections, 0); +});